Getting form widget name in Symfony2/Twig - symfony

So, what I need to do is to output current element's ID in each field_row. What I came to is overriding Symfony's default field_row block with the following code:
{% block field_row %}
{% spaceless %}
<div class="clearfix" id="{{ form.get('name') }}-row">
{{ form_label(form) }}
<div class="input">
{{ form_widget(form) }}
</div>
</div>
{% endspaceless %}
{% endblock field_row %}
However, the {{ form.get('name') }} construct seems pretty awkward to me and I'm sure there's a more civilised way of doing this. Anyone?

Do you mean the id generated by symfony? then it's just:
{{ id }}

Related

Drupal 8 - page.html.twig not updating website

I am new to Drupal, and I'm creating a custom theme based on a Bootstrap Bario subtheme on Drupal 8.
I can update the CSS with no problem, but I first need to clear the cache before reloading the page (which gets annoying, is there a way to avoid that?).
This is how the theme's regions are arranged:
I added the help: 'Help' region in the .info.yml file, under the line footer_fifth: 'Footer Fifth', and the added Help region appears in the Block Layout page.
I then modified the relevant parts of templates/_page.html.twig like so:
From this
{% block footer %}
<div class="{{ container }}">
{% if page.footer_first or page.footer_second or page.footer_third or page.footer_fourth %}
<div class="site-footer__top clearfix">
{{ page.footer_first }}
{{ page.footer_second }}
{{ page.footer_third }}
{{ page.footer_fourth }}
</div>
{% endif %}
{% if page.footer_fifth %}
<div class="site-footer__bottom">
{{ page.footer_fifth }}
</div>
{% endif %}
</div>
{% endblock %}
to this
{% block footer %}
<div class="{{ container }}">
{% if page.footer_first or page.footer_second or page.footer_third or page.footer_fourth or page.footer_fifth %}
<div class="site-footer__top clearfix">
{{ page.footer_first }}
{{ page.footer_second }}
{{ page.footer_third }}
{{ page.footer_fourth }}
{{ page.footer_fifth }}
</div>
{% endif %}
{% if page.help %}
<div class="site-footer__bottom">
{{ page.help }}
</div>
{% endif %}
</div>
{% endblock %}
As you can see, I added or page.footer_fifth to the first if statement, moved {{ page.footer_fifth }} to the site-footer__top div, and added {{ page.help }} in its place.
After that, I go and clear the cache, but the block regions are still the same. If I inspect my block in the Footer Fifth region, it is still in the <div class="site-footer__bottom">.
Did I miss something?
Thank you in advance.
I think the template file name is wrong. See:
templates/_page.html.twig usually should be:
templates/page.html.twig
the complete path of your template should be "/themes/custom/yourthemename/".
PS: theme debug will help you in case of any doubt.
https://www.drupal.org/docs/theming-drupal/twig-in-drupal/debugging-twig-templates

Symfony2, a label Token appears when using form themes

I'm using Symfony2.6 , and I'm trying to customize form rendering. The problem that when I put {{ form_rest(form) }} into the form , a label Token appears. How can I make it hidden ?
This is the form theme
{% extends 'form_div_layout.html.twig' %}
{% block form_widget_simple %}
<div class="form-group">
{{ form_label(form, null, {'label_attr': {'class': 'control-label'}}) }}
{{ parent() }}
</div>
{% endblock %}
When I remove the block {% block form_widget_simple %} to test what gives , the Token label become hidden.
Edit:
I'd like to know also if it's correct to change the simple widget block and render inside it a label or no.
You've changed the block of the simple widget which shouldn't render a label (and it doesn't by default). If you really need to do it this way, you may check the type variable and do not render label for the hidden type. Something as following:
{% block form_widget_simple %}
<div class="form-group">
{% if type != 'hidden' %}
{{ form_label(form, null, {'label_attr': {'class': 'control-label'}}) }}
{% endif %}
{{ parent() }}
</div>
{% endblock %}
This works fine :
{% extends 'form_div_layout.html.twig' %}
//........
{%- block hidden_row -%}
<div style="display:none">
{{ form_widget(form) }}
</div>
{%- endblock hidden_row -%}

How do I add a class to each expanded form widget in Symfony2?

Here are the Twig fields I'm trying to override: github
I have a list of checkbox that has been modified with this custom form theme:
{% block choice_widget_expanded %}
{% spaceless %}
<div {{ block('widget_container_attributes') }}>
{% for child in form %}
<div class="checkbox_row">
{{ form_widget(child) }}
{{ form_label(child) }}
</div>
{% endfor %}
</div>
{% endspaceless %}
{% endblock choice_widget_expanded %}
I tried adding a class using {{ form_row(form.fieldName), {'attr':{'class':'myclass'}}) }}
But that only adds a class to the div#formName_fieldName. Next I tried adding a custom block with
{% block _formName_fieldName_widget %}
{% spaceless %}
<input type="checkbox" {{ block('widget_attributes') }} value="{{ value }}" class="myclass_{{ value }}" />
{% endspaceless %}
{% endblock choice_widget_expanded %}
Notice I also included the value as I want to have myclass_1, myclass_2 etc.
The problem with this is that the block receives an array so it should be like this
{% block _fb_post_facebook_pages_widget %}
{% spaceless %}
<div {{ block('widget_container_attributes') }}>
{% for child in form %}
{{ form_widget(child) }}
{{ form_label(child) }}
{% endfor %}
</div>
{% endspaceless %}
{% endblock choice_widget_expanded %}
But then if I wanted to add the class to a specific checkbox, I would need to write something like this:
{% block _formName_fieldName_X_widget %}
{% spaceless %}
<input type="checkbox" {{ block('widget_attributes') }} value="{{ value }}" class="myclass_{{ value }}" />
{% endspaceless %}
{% endblock choice_widget_expanded %}
Where X would be a value that I have for the fieldName... And obviously the values could be anything so I can't just create block for all values from 1-1000000000000...
Any way to do this dynamically?
You would need to extend Twig, I believe. You can then specify the code in PHP and just bring in the conditions.
http://twig.sensiolabs.org/doc/advanced.html

Defining custom twig form block for errors rendering

I'm trying to define a specific new block for form field errors rendering, keeping form_errors unchanged for common errors rendering.
# Twig Configuration
twig:
debug: %kernel.debug%
strict_variables: %kernel.debug%
form:
resources:
- 'ApplicationMyBundle:Main:form/customFormTheme.html.twig'
In customFormTheme.html.twig I overwrite a few blocks copied from form_div_layout.html.twig plus I added the folloowing new one.
{% block field_errors %}{% spaceless %}
{% if errors|length > 0 %}
<ul class="errors">
{% for error in errors %}
{% if error.messageTemplate|length %}
<li class="error">{{ error.messageTemplate|trans(error.messageParameters, 'validators') }}</li>
{% endif %}
{% endfor %}
</ul>
{% endif %}
{% endspaceless %}{% endblock %}
Then I expect to be able to use this block in my views like this :
<div>
{{ form_label(form.message, 'message.label'|trans({},'contact')|raw ) }}
{{ form_widget(form.message, {attr: {maxlength:1000, size:1000, rows:8}}) }}
{{ field_errors(form.message) }}
</div>
but I receive the following error :
The function "field_errors" does not exist. Did you mean "form_errors"
I also tried by naming my block text_errors or textarea_errors mentioned here but I haven't been luckier.
Any idea ?
Actually it works by defining the block text_errors or textarea_errors only and still use {{ form_errors(field.name) }} in your template. If a block named after the type of your field exists (according to form field types) it will be used instead of form_errors.
!! But you can't use directly {{ text_errors(field.name) }} in your twig template !!
The same way you can have a custom row for a specific type like this
{% block textarea_row %}{% spaceless %}
<div class="textarea l-field {{ (form_errors(form)?'error':'') }}">
{{ form_label(form) }}
{{ form_widget(form) }}
{{ form_errors(form) }}
</div>
{% endspaceless %}{% endblock textarea_row %}
and use it in your template as follow :
{# message has textarea field type #}
{{ form_row(form.message, {
label: 'message.label'|trans({},'contact')|raw ,
attr: {maxlength:1000, size:1000, rows:8}})
}}
You can also pass many custom parameters by using the object attr{}
{% block form_row %}
{% spaceless %}
<div class="form-field {{ (form_errors(form)?'error':'') }}">
{{ form_label(form) }}
{{ form_widget(form) }}
{{ dump(attr) }}
{% if attr.help is defined and not attr.help == '' %}<p class="form-help">{{ attr.help }}</p>{% endif %}
{{ form_errors(form) }}
</div>
{% endspaceless %}
{% endblock form_row %}
and use it like this
{{ form_row(form.message, {
label: 'message.label'|trans({},'contact')|raw ,
attr: {
maxlength:1000, size:1000, rows:8,
help: 'password.help'|trans({})|raw
}
})
}}

How to set a css class of the widget type with Symfony2

Is there a way to apply a specific class on the root div of an input depending on the input type ?
ex.:
<div class="radio-input">
<input...
....
</div>
I tried to overload "fields.html.twig" with this :
{% block form_row %}
{% spaceless %}
{% set type = type|default('text') %}
<div class="{{ type }}-input">
{{ form_label(form) }}
{{ form_errors(form) }}
{{ form_widget(form) }}
</div>
{% endspaceless %}
{% endblock form_row %}
But "type" is always equal to "text".
Not a particularly nice solution but it seems block_prefixes is passed to block form_row. Block_prefixes is an array of the form field types in order of inheritance so a text field called first name would have a block_prefixes array like:
block_prefixes = array("form","field","text","first_name")
Which means you could potentially get the second from last array element and use that:
{% block form_row %}
{% spaceless %}
<div class="{{ (block_prefixes|slice((block_prefixes|length - 2),1))|first }}-input">
{{ form_label(form) }}
{{ form_errors(form) }}
{{ form_widget(form) }}
</div>
{% endspaceless %}
{% endblock form_row %}
I'm sure there is a nicer way than this though I just don't have it to mind.
P.s type is undefined which is why its always text for you as you are setting it to default to text

Resources