Extend bootstrap_3_layout.html.twig form theme - forms

I am trying to customize the form layout in a symfony 3 project, by extending bootstrap_3_layout.html.twig form theme.
{# app/Resources/views/app/custom_bootstrap_metronic.html.twig #}
{% use "bootstrap_3_layout.html.twig" %}
{% block checkbox_widget -%}
{%- set parent_label_class =
parent_label_class|default(label_attr.class|default('')) -%}
{% if 'checkbox-inline' in parent_label_class %}
{{- form_label(form, null, { widget: parent() }) -}}
{% else -%}
<div class="checkbox">
{{- form_label(form, null, { widget: parent() }) -}}
</div>
{%- endif %}
{%- endblock checkbox_widget %}
and i added this in the configuration file:
{# app/config/config.yml #}
twig:
# form_themes: [bootstrap_3_layout.html.twig]
form_themes: [form/custom_bootstrap_metronic.html.twig]
what i want is to override the checkbox_widget so the rendered html will like:
<div class="form-group">
<div class="checkbox">
<label class="mt-checkbox">
<input type="checkbox" id="appbundle_accept"
name="appbundle[accept]" value="1">
Label
<span></span>
</label>
</div>
</div>
instead of:
<div class="form-group">
<div class="checkbox">
<label>
<input type="checkbox" id="appbundle_accept"
name="appbundle[accept]" value="1">
Label
</label>
</div>
</div>
I can't do that because the parent() function returns the checkbox_widget block from bootstrap_3_layout.html.twig and i need the checkbox_widget block from form_div_layout.html.twig

What i did is i copied the code from "bootstrap_3_layout.html.twig" in a file called "custom_bootstrap_metronic.html.twig" then i customized it.
{% block checkbox_widget -%}
{%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%}
{% if 'checkbox-inline' in parent_label_class %}
{{- form_label(form, null, { widget: parent(), label_attr: {class: 'mt-checkbox'}}) -}}
{% else -%}
<div class="mt-checkbox-inline">
{{- form_label(form, null, { widget: parent(), label_attr: {class: 'mt-checkbox'}}) -}}
</div>
{%- endif %}
{%- endblock checkbox_widget %}
{% block checkbox_radio_label %}
{# Do not display the label if widget is not defined in order to prevent double label rendering #}
{% if widget is defined %}
{% if required %}
{% set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' required')|trim}) %}
{% endif %}
{% if parent_label_class is defined %}
{% set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' ' ~ parent_label_class)|trim}) %}
{% endif %}
{% if label is not same as(false) and 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 %}>
{{- widget|raw }}
{{ label is not same as(false) ? (translation_domain is same as(false) ? label : label|trans({}, translation_domain)) -}}
<span></span> {# added this line #}
</label>
{% endif %}
{% endblock checkbox_radio_label %}

Related

Overriding the form rendering template according to the items

For example
I have two members in form object.
form_widget(form.icon)
form_widget(form.name)
I have changed 'choice_widget_expanded'
{% block choice_widget_expanded %}
{% spaceless %}
<table {{ block('widget_container_attributes') }}>
{% for child in form %}
<tr>
{{ form_widget(child) }}
{{ form_label(child) }}
</tr>
{% endfor %}
</table>
{% endspaceless %}
{% endblock choice_widget_expanded %}
However I would like to make it affect on {{form.icon}} only
is it possible ? how can I tell the object passed to this block is form.icon or form.name?
To override label block for choice_widget_expanded you can define your block and use it like in below
{% block choice_widget_expanded %}
{% spaceless %}
<table {{ block('widget_container_attributes') }}>
{% for child in form %}
<tr>
{{ form_widget(child) }}
{{ form_label_custom(child) }}
</tr>
{% endfor %}
</table>
{% endspaceless %}
{% endblock choice_widget_expanded %}
And for the custom label too form_label_custom
Note now for every choice field with expanded property (not all
fields) your new label will be in action
{% block form_label_custom %}
{% spaceless %}
{% if label is not sameas(false) %}
{% if not compound %}
{% set label_attr = label_attr|merge({'for': id}) %} /* you can skip this part for td */
{% endif %}
{% if required %}
{% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' required')|trim}) %}
{% endif %}
{% if label is empty %}
{% set label = name|humanize %}
{% endif %}
<td {% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>{{ label|trans({}, translation_domain) }}</td>
{% endif %}
{% endspaceless %}
{% endblock form_label_custom %}
Or even more you can define the custom form_widget_custom(child) block to override like
{% block form_widget_custom %}
{% spaceless %}
{% if compound %}
{{ block('form_widget_compound') }}
{% else %}
{{ block('form_widget_simple') }}
{% endif %}
{% endspaceless %}
{% endblock form_widget_custom %}
And now render your field
{{ form_widget_custom(form.icon) }}

Symfony2 form - Customize birthday type

How can I customize birthday type in Symfony2? There is no
{% block birthday_widget %}
in form_div_layout
The birthday form type gets rendered with the block choice_widget.
{% block choice_widget %}
{% spaceless %}
{% if expanded %}
{{ block('choice_widget_expanded') }}
{% else %}
{{ block('choice_widget_collapsed') }}
{% endif %}
{% endspaceless %}
{% endblock choice_widget %}
In the end, the block doing the output is named choice_widget_collapsed. Just make your changes in there.
{% block choice_widget_collapsed %}
{% spaceless %}
{% if required and empty_value is none and not empty_value_in_choices %}
{% set required = false %}
{% endif %}
<select {{ block('widget_attributes') }}{% if multiple %} multiple="multiple"{% endif %}>
{% if empty_value is not none %}
<option value=""{% if required and value is empty %} selected="selected"{% endif %}>{{ empty_value|trans({}, translation_domain) }}</option>
{% endif %}
{% if preferred_choices|length > 0 %}
{% set options = preferred_choices %}
{{ block('choice_widget_options') }}
{% if choices|length > 0 and separator is not none %}
<option disabled="disabled">{{ separator }}</option>
{% endif %}
{% endif %}
{% set options = choices %}
{{ block('choice_widget_options') }}
</select>
{% endspaceless %}
{% endblock choice_widget_collapsed %}

symfony2 twig referencing base widget

I am trying to customize my symfony2 form choice_widget_expanded part, and trying to reference the base (standard) for the choice_widget_collapsed as per this instruction http://symfony.com/doc/current/cookbook/form/form_customization.html
But I get an error saying
Notice: Undefined index: choice_widget_collapsed in /var/www/beta/app/cache/dev/twig/ff/8a/9f46c90c543b16e78e981aeda67b.php line 19
Here is my twig code:
{% extends '::base.html.twig' %}
{% use 'form_div_layout.html.twig' with choice_widget_collapsed as base_choice_widget_collapsed %}
{% form_theme form _self %}
{% block choice_widget %}
{% spaceless %}
{% if expanded %}
{{ block('choice_widget_expanded') }}
{% else %}
{{ block('base_choice_widget_collapsed') }}
{% endif %}
{% endspaceless %}
{% endblock choice_widget %}
{% block choice_widget_expanded %}
{% spaceless %}
<div {{ block('widget_container_attributes') }}>
{% for child in form %}
{{ form_widget(child) }}
{{ form_label(child) }}
<br />
{% endfor %}
</div>
{% endspaceless %}
{% endblock choice_widget_expanded %}
{% block contents %}
This works for me on a fresh composer install of sf 2.2.1. You should not need to clear cache for template changes to register in the dev environment, but it's worth a shot. It could also be that you need to stop and start (not restart) apache/php5-fpm if using an opcode cache.
Since you're only modifying choice_widget_expanded all you really need is:
test.html.twig
{% extends '::base.html.twig' %}
{% form_theme form _self %}
{% block choice_widget_expanded %}
{% spaceless %}
<div {{ block('widget_container_attributes') }}>
{% for child in form %}
{{ form_widget(child) }}
{{ form_label(child) }}
<br />
{% endfor %}
</div>
{% endspaceless %}
{% endblock choice_widget_expanded %}
{% block body %}
<form>
{{ form_row(form.choice) }}
</form>
{% endblock %}
testAction
/**
* #Template()
*/
public function testAction()
{
$builder = $this->createFormBuilder();
$builder->add('choice', 'choice', array(
'choices'=>array('one'=>'one', 'two'=>'two', 'three'=>'three'),
'expanded'=>true
));
$form = $builder->getForm();
return array('form'=>$form->createView());
}
Ah.. I am sure Dylans answer is correct, but for the symfony2 version I use (2.0.16) the template for that form looks a little different, the choice_widget_expanded doesn't have it's own block but it is all in this
{% block choice_widget %}
{% spaceless %}
{% if expanded %}
<div {{ block('widget_container_attributes') }}>
{% for child in form %}
{{ form_widget(child) }}
{{ form_label(child) }}
<br /> {# <-------- Here's my addition to the template #}
{% endfor %}
</div>
{% else %}
<select {{ block('widget_attributes') }}{% if multiple %} multiple="multiple"{% endif %}>
{% if empty_value is not none %}
<option value="">{{ empty_value|trans }}</option>
{% endif %}
{% if preferred_choices|length > 0 %}
{% set options = preferred_choices %}
{{ block('widget_choice_options') }}
{% if choices|length > 0 and separator is not none %}
<option disabled="disabled">{{ separator }}</option>
{% endif %}
{% endif %}
{% set options = choices %}
{{ block('widget_choice_options') }}
</select>
{% endif %}
{% endspaceless %}
{% endblock choice_widget %}
I Should of course have pulled the code out of my own codebase instead of grabbing the latest version off of github, doh!

How to customize form_label block in form template in Symfony2?

I'm trying to customize form_label in a template which already extends one template.
I'm using example in the Symfony2 documentation:
{% 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 %}
but nothing change!
Can you help me?
Here is my solution.
In top of my form.html.twig file:
{% form_theme form with 'MyBundle:Activity:Form/fields.html.twig' %}
and now into fields.html.twig, I custom the form_label:
{% extends 'form_div_layout.html.twig' %}
{% block form_label %}
{% spaceless %}
{% 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 %}
{% set label = name|humanize %}
{% endif %}
<label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>{{ label|trans({}, translation_domain) }}{% if attr.note is defined %} <span style="font: 11px normal; font-family: arial;">({{ attr.note }})</span>{% endif %}</label>
{% endspaceless %}
{% endblock form_label %}

Symfony2 form widget container attributes

I need set a class for widget container, but have no idea how Symfony passes attributes to "widget_container_attributes" block
Widget container template:
{% block form_widget %}
{% spaceless %}
<div {{ block('widget_container_attributes') }}>
{{ block('field_rows') }}
{{ form_rest(form) }}
</div>
{% endspaceless %}
{% endblock form_widget %}
Example result:
<div class="MY-CLASS">
<label class="required" for="page_title">Title</label>
<input type="text" value="Next subpage" maxlength="500" required="required" name="page[title]" id="page_title">
</div>
how can I do that?
try
{% extends 'form_div_layout.html.twig' %}
{% block field_rows %}
{% spaceless %}
{% for child in form %}
{{ form_row(child) }}
{% endfor %}
{% endspaceless %}
{% endblock field_rows %}
{% block field_row %}
{% spaceless %}
<div class="myclass">
{{ form_label(form, label|trans) }}
{{ form_widget(form) }}
{{ form_errors(form) }}
</div>
{% endspaceless %}
{% endblock field_row %}