How can you output HTML as entities in Twig? - symfony

I have widget examples that I need to output the HTML of so that people can copy and paste them onto their own websites. How can I escape the output so that it doesn't get rendered?

Ended up doing this, the key to the problem is using the escape filter as a block, the rest accounts for need for no spaces around <pre/><code/>'s to get the desired output:
<pre>
{%- spaceless -%}
<code>
{%- filter escape -%}
{% spaceless %}
{% include 'ACMEDemoBundle:Example:widget.html.twig' %}
{% endspaceless %}
{%- endfilter -%}
</code>
{%- endspaceless -%}
</pre>

Related

symfony's form_errors displays list item instead of just text

[ Symfony 4 ]
I've this template code in Symfony:
{{ form_widget(registrationForm.username, {'attr': {'class': 'form-control'}}) }}
{{ form_errors(registrationForm.username) }}
Instead of just displaying error text, it's generating a list item like this:
<ul><li> Username already exists </li></ul>
How to not have it generate this list item and just get the text?
I guess it is correct behavior, cause you can have multiple errors for one field for example "Username is too short" and "Field Username contains inappropriate characters", but to get only first error you can use:
{{ form_errors(registrationForm.username|first) }}
Or you can customize your form_errors rendering, first create file for form_errors, for example your_form/custom_form_errors.html.twig :
{% block form_errors %}
{% spaceless %}
<div class="error">{{ errors|first }}</div>
{% endspaceless %}
{% endblock %}
And after that include it to your view file:
{% form_theme form 'your_form/custom_form_errors.html.twig' %}
...
{{ form_errors(registrationForm.username) }}
just to extend #Andrii Filenko 's answer. You can modify the output the form_errors or any other form twig function pretty easily. it's called custom theming in Symfony.
Consider this:
// templates/register.html.twig
{% extends "base.html.twig" %}
{% form_theme registrationForm _self %}
{% block form_errors %}
{% spaceless %}
{% if errors|length > 0 %}
<ul class="changed list">
{% for error in errors %}
<li>{{ error.message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endspaceless %}
{% endblock form_errors %}
{% block body %}{% endblock %}
Output:
<ul class="changed list"><li> Username already exists </li></ul>

Twig Runtime Error: Impossible to invoke a method ("test") on a string variable

I have the following twig template (the code is in the same file):
{% macro renderJob(fields) %}
// renders the job UI block, but I've removed it for simplicity
Hello world.
{% endmacro %}
{% block _jobs_widget %}
<div id="jobsContainer">
{% for fields in form.children %}
{% dump fields %}
{{ _self.renderJob(fields) }}
{% endfor %}
</div>
{% endblock %}
For some reason, after upgrading to twig/twig = v2.1.0 I'm receiving the follwing error:
Impossible to invoke a method ("renderJob") on a string variable ("#AppBundle/Jobs/form/job.html.twig").
I have been trying to figure out what's causing this without any luck. This used to work just fine in 1.3.x. The fields variable contains the proper data, but it appears it can't pass it to the renderJob macro or it can't find the macro (which is kind of odd)?
Have you tried the following ?
{% import _self as renderJobMacro %}
{% macro renderJob(fields) %}
// renders the job UI block, but I've removed it for simplicity
Hello world.
{% endmacro %}
{% block _jobs_widget %}
<div id="jobsContainer">
{% for fields in form.children %}
{{ renderJobMacro.renderJob(fields) }}
{% endfor %}
</div>
{% endblock %}
I think _self is depricated from twigg 2.0, May be you need to check without _self.
Check {{ renderJob(fields) }} instead of {{ _self.renderJob(fields) }}

how to change a label template using twig inheritance in symfony2

Using Symfony2.3.4 with Twig.
Say I´m trying to add, for example, a colon (:) and, if required, an asterisk (*) to every label of every field in a form generated by Symfony2's CRUD. For this I'm using a twig template to inherit Symfony2's main template form_div_layout.html.twig.
So far:
//config.yml
twig:
form:
resources:
- ::my_form_layout.html.twig
//my_form_layout.html.twig
{% block form_label %}
{% spaceless %}
{% if label is not sameas(false) %}
...
{% set asterisk = '<sup><i title="Campo obligatorio"
class="glyphicon-asterisk" style="color: red; font-size:
8px"></i></sup>' %}
<label {% for attrname, attrvalue in label_attr %}
{{ attrname }}="{{ attrvalue }}"{% endfor %}>
{{ label|trans({}, translation_domain) }}: {% if required %}
{{ asterisk|raw }} {% endif %}
</label>
...
{% endif %}
{% endspaceless %}
{% endblock form_label %}
Problem is this way when I render, for example, a choice-type field for selecting the sex of a person, with expanded and required set to TRUE, the colon (:) and the asterisk (*) appear next to the word Sex AND the words Male and Female as well.
How can I make the template differenciate between the parent and the two children, so the colon and the asterisk appear only after the word Sex.
Thanx
This is how I've done something similar. Modify the 'choice_widget_expanded' block a bit in your custom form layout:
// update this row: {{ form_label(child) }}
{{ form_label(child, child, {'exclude_additions': 'true'}) }}
And update your 'form_label' to check whether this value is defined:
{{ label|trans({}, translation_domain) }}{% if exclude_additions is not defined %}: {% if required %}
{{ asterisk|raw }} {% endif %} {% endif %}

Avoid twig block output

I have the following twig template
{%- block block1 -%}
<div class="test">
{{ block('block2') }}
</div>
{%- endblock block1 -%}
{%- block block2 -%}
<div>Test2</div>
{%- endblock block2 -%}
The Result is:
<div class="test">
<div>Test2</div>
</div><div>Test2</div>
But should be:
<div class="test">
<div>Test2</div>
</div>
I want todo something like the form template in symfony: https://github.com/symfony/symfony/blob/2.7/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig
UPDATE:
The only solution would be to add an if false which looks not very nice:
{%- block block1 -%}
<div class="test">
{{ block('block2') }}
</div>
{%- endblock block1 -%}
{% if false %}
{%- block block2 -%}
<div>Test2</div>
{%- endblock block2 -%}
{% endif %}
Why do you want to define your blocks this way? Or put it in other words: You can simply define the second block inside the first block like this:
{%- block block1 -%}
<div class="test">
{%- block block2 -%}
<div>Test2</div>
{%- endblock block2 -%}
</div>
{%- endblock block1 -%}
If you separate the result you get in a different way, it will help you see what is happening:
// block1 with block2 inserted
<div class="test">
<div>Test2</div>
</div>
// block2
<div>Test2</div>
i.e. when you define block2 it is not only inserted into block1, it is also rendered at the place where it is defined. You may try to build this functionality some other way, perhaps by using the include function
you have to add your form theme to render these custom blocks or like Carlos Granados saying you have to include other twig here.
Which link you are showing is symfony2 form theme which will render when form blocks will call and it is doing it because you tell symfony2 to do it. In your layout twig add file like this -
{% form_theme form "UrBundle:Default:fields.html.twig" %}
it will be your file which will render your blocks - fields.html.twig,
here you can define your blocks and then can access those in current like -
{% block block1 %}
{{ parent() }}
{% endblock %}
it's out will be like you want link
In twig, the main template rendered will always render all of the blocks "included" in the template, even with extends. Instead you're attempting to create horizontal reuse blocks.
In order to produce your desired result, you would need to implement a {% use 'blocks.twig' %}
This approach is highly subjective to what you intend to accomplish and is not typically needed in regular templates.
Example https://twigfiddle.com/fwjpl8
{# main.html.twig #}
{% use 'info.blocks.twig' %}
{%- block content -%}
{%- set data = { name: 'Test', place: 'Test2' } -%}
{{ block('data') }}
{%- endblock -%}
{# info.blocks.twig #}
{%- block data -%}Data {{ data.name }} {{ block('data_place') }}{%- endblock -%}
{%- block data_place -%}{{ data.place }}{%- endblock -%}
Result:
Data test test2
Do keep in mind there are limitations on use.
The use tag only imports a template if it does not extend another
template, if it does not define macros, and if the body is empty. But
it can use other templates.
So you can not do
{# main.html.twig #}
{% use 'info.blocks.twig' %}
{# info.blocks.twig #}
{% extends 'other.blocks.twig' %}
{%- block data -%}Data {{ data.name }} {{ block('data_place') }}{%- endblock -%}
{%- block data_place -%}{{ data.place }}{%- endblock -%}

Customising form labels in Symfony

I have a symfony page where I display a form, and I would like to add an
* in the labels of all fields that are required.
So I have my form.php.twig, that looks like this:
{% extends "::layout.php.twig" %}
{% block body %}
<div class="row">
{% use 'form_div_layout.html.twig' with form_label as base_form_label %}
{% block form_label %}
{{ block('base_form_label') }}
{% if required %}
<span class="required" title="This field is required">*</span>
{% endif %}
{% endblock %}
</div>
{% endblock %}
I followed the exact documentation of the symfony cookbook on how to customise labels, which is http://symfony.com/doc/current/cookbook/form/form_customization.html#cookbook-form-theming-methods.
But I keep getting this error
Variable "label" does not exist in form_div_layout.html.twig at line 206
I don't have any label variable in the code of my form.php.twig so I don't see why I get this error. And when I remove the
{{ block('base_form_label') }}
I get
Variable "required" does not exist in ATPlatformBundle:Session:create.php.twig
Can anyone help me on this? I don't see where is my mistake? I am not looking to customise it with css, but to add the * .
I have checked the form_div_layout.html.twig at line 206 and this is what there is
{%- block form_label -%}
{% if label is not sameas(false) -%}
{% if not compound -%}
{% set label_attr = label_attr|merge({'for': id}) %}
{%- endif %}
{% if required -%}
{% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' required')|trim}) %}
{%- endif %}
{% if label is empty -%}
{%- if label_format is not empty -%}
{% set label = label_format|replace({
'%name%': name,
'%id%': id,
}) %}
{%- else -%}
{% set label = name|humanize %}
{%- endif -%}
{%- endif -%}
<label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>{{ translation_domain is sameas(false) ? label : label|trans({}, translation_domain) }}</label>
{%- endif -%}
{%- endblock form_label -%}
Thank you in advance.
Did you try defining the label from inside your form builder?! The below field is a required one because unless you mention required => false, your field will be rendered as required.
Something like:
->add('name', 'text', array('label' => '* name'))
With Twig, you should have to test the existence of a variable before using it:
Variable "required" does not exist
{% if required is defined and ... }
You need to test this because you field isn't always required.
if you want further information, you have this page of the documentation:
http://twig.sensiolabs.org/doc/tests/defined.html
Ok, so at the end, I didn't manage to change labels within my form.php.twig (which is the template I use to display my form), but I used another technique.
I created a new file named fields.php.twig, which I put in MyBundle/Resources/views/Form.
At the beginning of my fields.php.twig, I then added
{% extends 'form_div_layout.html.twig' %}
and below it, I added
{% block form_label %}
{{ parent() }}
{% if required %}
<span> * </span>
{% endif %}
{% endblock form_label %}
Then in my form.php.twig, I added
{% form_theme form 'MyBundle:Form:fields.php.twig' %}
{{ form_start(form) }}
Myform here with {{ form_label(form.property) }}
{{ form_errors(form.property) }}
{{ form_widget(form.property) }}
{{ form_end(form) }}
It works perfectly, but I had to create the fields.php.twig.

Resources