Symfony 4 EasyAdmin - Property does not render when overriding bundle template - php

Using Symfony 4.1 with EasyAdmin bundle.
I am trying to override a template for the User (one of my entites) show view. I have set up the override and it is working.
Created a user_show.html.twig and registered it in the easy_admin config file.
I then copy the twig blocks from corresponding bundle template for show.html.twig.
Then tried to render a User property from my user entity, called profile height.
Here are twig blocks I'm overriding:
{# templates/admin/user_show.html.twig #}
{% extends '#EasyAdmin/default/show.html.twig' %}
{% block content_title %}
Test Title {{ dump() }}
{% endblock %}
{% block main %}
{{ profileHeight }}
{% endblock %}
Error
Twig_Error_Runtime: Variable "profileHeight" does not exist
Debug
I did a dump and found the property is present on page:
Why can twig not see these variables appearing in the dump? How can I render the properties I want in the template?

As you can see in your dumped data, there is entity array key which hold the User object. So instead of:
{% block main %}
{{ profileHeight }}
{% endblock %}
Use:
{% block main %}
{{ entity.profileHeight }}
{% endblock %}

Related

Print debug stack trace (within block)

Trying to extend a formbuilder plugin for Pimcore (https://github.com/dachcom-digital/pimcore-formbuilder) I am trying to modify the output of input/select fields in order to be compatible with MD Bootstrap syntax.
Therefore I override /FormBuilderBundle/Form/Theme/bootstrap_4_layout.html.twig. The shortened content of this file is like this:
{% extends 'bootstrap_4_layout.html.twig' %}
{% use '#FormBuilder/Form/Theme/Type/dynamic_multi_file.html.twig' %}
{% use '#FormBuilder/Form/Theme/Type/html_tag.html.twig' %}
{% use '#FormBuilder/Form/Theme/Type/snippet.html.twig' %}
{% use '#FormBuilder/Form/Theme/Type/container.html.twig' %}
{% block form_row -%}
{% set form_row_class = attr['data-template'] is defined ? attr['data-template'] : 'col-12' %}
{% if form.vars.is_form_builder_container_block is defined %}
{% set form_row_class = 'formbuilder-container-block' %}
{% endif %}
<div class="formbuilder-row md-form {{ form_row_class }}">
{{ parent() }}
</div>
{%- endblock form_row %}
The problem is that there is no other file called bootstrap_4_layout.html.twig (except in the macros folder) and the template can not extend itself. I want to find out what the parent() function is doing here in order to alter the output (https://twig.symfony.com/doc/3.x/functions/parent.html).
As I still did not find the template which is extended I would like to print the parent() functions' stack trace in order to know which files are involved. Is there any possibility to do this with Twig (maybe with a Twig Extension)?

How can I pass variable from parent template to child template in Twig?

I'm working with Symfony and Twig and I can't find solution for the next problem:
in my parent template (index.html.twig) I have such code:
<noscript>
{% block noscript %}
<div class="alert alert-warning">
<strong>{% block notice %}{{ notice_js_disabled }}{% endblock %} </strong>
{% block message %}{{ js_disabled }}{% endblock %}
</div>
{% endblock %}
</noscript>
I have child template (category.html.twig) which extends index.html.twig template.
Can I pass value of {{ notice_js_disabled }} var from index template to category template?
notice_js_disabled is returned from my Symfony indexAction controller.
UPD:
The solution for my problem I founded, next:
I have made base templae, called main.html.twig, where I'm rendering element from the controller:
{% block header %}
{{ render(controller('StoreBundle:Header:index')) }}
{% endblock %}
Then, on my index.html.twig file, I made next things:
{% extends 'Store/tpl/main.html.twig' %}
{% block title %}{{ title }}{% endblock %}
{% block content %}
<p class="currentPage" hidden>home</p>
{{ parent() }}
{% endblock %}
I'm not sure is it correct solution, but it's work:)
The only way in Twig you can pass some variable to a child template is by the include tag.
{# template.html will have access to the variables from the current context and the additional ones provided #}
{% include 'template.html' with {'foo': 'bar'} %}
{% set vars = {'foo': 'bar'} %}
{% include 'template.html' with vars %}
However in this way you are not extending some parent template from the child, but you are doing the other way around: you are placing a submodule into the current template.
There are only a couple of variables which are global in symfony
You can set some custom global variables in configuration like described here
Otherwise you can use some predefined global variables, the app variable. (check it out here)
My personal advice is that you should review your application template logic.
Hope it helps!
What you have to do is the following:
-Create A variable in the parent template
{% set notice_js_disabled = value_received_from_indexAction %}
After the template that you need that value
{{ notice_js_disabled }}
I hope it helps you

Symfony2/Twig - how to set template file contents as variable?

In Symfony 2.8 I've got SharedBundle, where I keep views and other things I share between other bundles, including the whole layout that should be extended by other bundles' views.
That shared layout has some typical blocks, from which sidebar block should be different for different bundles.
Currently I did an ugly workaround:
In SharedBundle sidebar container:
{% if sidebarcontent is defined %}
{{ sidebarcontent|raw }}
{% else %}
SIDEBAR NOT FOUND
{% endif %}
And in other bundles (here: BundleA) in every view that extends the shared main view:
{% extends 'SharedBundle:layout.html.twig' %}
{% block sidebar %}
{% include 'BundleA:_partials:sidebar.html.twig' %}
{% endblock %}
{% set sidebarcontent = block('sidebar') %}
But that doesn't look good, I think. Is there a better way?
I think this is a valid approach. The only simplification I can think of is not using the variable sidebarcontent.
You can use block('sidebar') inside the if statement:
{% if block('sidebar')|length > 0 %}
{{ sidebarcontent|raw }}
{% else %}
SIDEBAR NOT FOUND
{% endif %}
Make sure the block exists before checking it's content, so initialise it with an empty string:
{% block sidebar %}{% endblock %}

Twig Inheritance: get raw resulting template

I'm developing Symfony2 + Twig project. I need to get raw not interpeted template (variables shouldn't be replaced) string in Symfony2 Controller after merging with its parent template.
For example:
parent.html.twig
{% block title %}
Parent Content
{% endblock %}
child.html.twig
{% extends "parent.html.twig" %}
{% block title %}
{{ parent() }}
{{ CHILD_CONTENT }}
{% endblock %}
Desirable result is a string:
Parent Content
{{ CHILD_CONTENT }}
I've heard about source function in 1.15 version, but it doesn't handle inheritance.
Is there any way to get around?
already tried "verbatim"? http://twig.sensiolabs.org/doc/tags/verbatim.html
Your code should look like this:
{% block title %}
{{ parent() }}
{% verbatim %}
{{ CHILD_CONTENT }}
{% endverbatim %}
{% endblock %}
This should solve your problem.

How to override the "form_div_layout" base template?

I want to override the base tempale to be used in twig.
I have used this
twig:
form:
resources:
- 'form_div_layout.html.twig'
and I have copied the file from original location to
app/resources/views/Form/form_div_layout.html.twig but still I am not able to see the changes in template rendering.
Basically I just want to add the class in DIV box generated
{% block form_widget_compound %}
{% spaceless %}
<div class="MYCLASS"
{{ block('widget_container_attributes') }}>
{% if form.parent is empty %}
{{ form_errors(form) }}
{% endif %}
{{ block('form_rows') }}
{{ form_rest(form) }}
</div>
{% endspaceless %}
{% endblock form_widget_compound %}
Do I need to make any more change ?
You donĀ“t need to copy the full file if you just want to customize one field. Do this:
If you just want to do this for just one template, add this to your template:
{% form_theme form _self %}
{% block form_widget_compound %}
{% spaceless %}
<div class="MYCLASS" >
{{ block('widget_container_attributes') }}>
{% if form.parent is empty %}
{{ form_errors(form) }}
{% endif %}
{{ block('form_rows') }}
{{ form_rest(form) }}
</div>
{% endspaceless %}
{% endblock form_widget_compound %}
If you want to customize this in several templates, do this: create a template file in your bundle with this code:
{# src/Acme/DemoBundle/Resources/views/Form/fields.html.twig #}
{% block form_widget_compound %}
{% spaceless %}
<div class="MYCLASS" >
{{ block('widget_container_attributes') }}>
{% if form.parent is empty %}
{{ form_errors(form) }}
{% endif %}
{{ block('form_rows') }}
{{ form_rest(form) }}
</div>
{% endspaceless %}
{% endblock form_widget_compound %}
Then in those templates where you want to use this customized field, do:
{% form_theme form 'AcmeDemoBundle:Form:fields.html.twig' %}
If you want this customization to be available in ALL templates of a bundle, add this to your config file:
# app/config/config.yml
twig:
form:
resources:
- 'AcmeDemoBundle:Form:fields.html.twig'
If you want this to be available for ALL bundles, copy this file to
app/Resources/AcmeDemoBundle/views/Form/fields.html.twig
To do what you are trying copy just form_div_layout.html.twig in resources without the Form folder and then in config reffer to it this way: ::form_div_layout.html.twig
twig:
form:
resources:
- '::form_div_layout.html.twig'
You don't have to copy all of it. You can extend only parts of it..
Here it is, plain and simple. To override only certain blocks application-wide you must use a different file name than form_div_layout.html.twig otherwise you will get errors. If you copy the entire file and make changes, this isn't a problem. But if you only want to override some of the blocks, this is how you do it:
Create the file app/Resources/views/forms.html.twig and paste in the blocks you want to customize. The filename isn't important as long as it is not form_div_layout.html.twig.
Next add this to the twig configuration in app/config/config.yml
# app/config/config.yml
twig:
form:
resources: ["::forms.html.twig"]
To make full global override of original form_div_layout.html.twig template but NOT copy entire file do next
Theory:
Add twig load path for original file (to avoid requrssion)
Optional. Add explicit form_themes
Place in your default path new 'form_div_layout.html.twig'
extend in the new file from the original by [path] namescpace
So. Practice
In your symfony twig config place it:
# symfony/config/packages/twig.yaml
twig:
default_path: '%kernel.project_dir%/templates'
# 1 step
paths:
- value: '%kernel.project_dir%/../vendor/symfony/twig-bridge/Resources/views/Form/'
namespace: 'TwigBridge'
form_themes:
- '#SonataForm/Form/datepicker.html.twig'
# 2nd
- 'form_div_layout.html.twig'
Create new file symfony dir/templates/form_div_layout.html.twig
# '%kernel.project_dir%/templates'
# OR
# templates/form_div_layout.html.twig*
{#{% extends 'vendor/symfony/twig-bridge/Resources/views/Form/form_div_layout.html.twig' %}#}
{% extends '#TwigBridge/form_div_layout.html.twig' %}
# make override - replace original form widget
{%- block dateinterval_widget -%}
{{ parent() }}
{%- endblock dateinterval_widget -%}
To make local overrides see other answers.

Categories