Symfony2 how to render Checkboxes? - symfony

I have a formbuilder form with a multiple choice list of countries. When I render them on my form like this:
{{ form_widget(edit_form.countries) }}
They appear like this:
<input type="checkbox" name="..." value="AD" /><label for="...">Andorra</label>
<input type="checkbox" name="..." value="AE" /><label for="...">United Arab Emirates</label>
<input type="checkbox" name="..." value="AF" /><label for="...">Afghanistan</label>
I would like each option displayed on it's own line in the browser, instead of all in a row. How can I inject html around or between the options? Or is there a CSS method to accomplish this?
Thanks.

From The Symfony Docs
Form theming
How to customize form rendering
Default form div layout
What you basically need to do is to overload checkbox_widget block.
{% form_theme form _self %}
{% block checkbox_widget %}
{% spaceless %}
<input type="checkbox" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />
{% endspaceless %}
{% endblock checkbox_widget %}
Of course you can place your widgets in its own line with CSS (but it's not a Symfony2 question).

A lazier way I found to do this was to iterate through the form/choice array.
At its simplest, rendering a form you might do:
{{ form_widget(form) }}
For a little more granularity, you might do:
{{ form_row(form.itemA) }}
{{ form_row(form.itemB) }}
{{ form_row(form.itemC) }}
But if "itemA" is a multi-choice, you're stuck with the entire list getting rendered on the same line. If you're looking for just a little more granularity before you step up to theming, you can do this:
{% for t in form.itemA %}
{{ form_row(t) }}
{% endfor %}
That'll render each checkbox on its own line, or give you an opportunity to do whatever you want between each item.

As Kuba has said in his answer this sounds partly like a CSS question. Semantically speaking injecting something like a <br /> tag doesn't have much meaning but you can do that if you wish by following the documents in Kuba's answer.
If you wish to write some CSS to get those elements to display line by line you can use this against symfony's default output:
input, label {
float: left;
}
input {
clear: left;
}
Of course this will actually cause all input and label tags to float left which might not be suitable to you so you can a) wrap your checkboxes in another div and use a css sub-selector like .checkboxes input, .checkboxes label or b) apply a custom css class to your widgets using:
{{ form_widget(form.name, { 'attr': {'class': 'foo'} }) }}
and the CSS would be the same but instead of input you'd have .foo.

Related

Custom radio button id in Twig

Code of rendered Twigs radio button set form usually looks like...
This:
{{ form_widget(formTitle.radioSet) }}
To this...
<input type="radio" id="formTitle_radioSet_0" name="formTitle[radioSet]" value="fooValue">
<input type="radio" id="formTitle_radioSet_1" name="formTitle[radioSet]" value="booValue">
... and a few more rows like this
I want to make it work with JS easier. Is it possible to render customized radio buttons with IDs reffered to the value of radio and my own preferences like this??
<input type="radio" id="radioSet_fooValue" name="formTitle[radioSet]" value="fooValue">
<input type="radio" id="radioSet_booValue" name="formTitle[radioSet]" value="fooValue">
After about half an hour of exploring article recommended by Carlos Granados got a solution. The target is to override twigs template of renderind radio inputs.
In a few words, code below, pasted at the beginning of your web page template will override ALL radio's render the way it described in question.
{% form_theme form _self %}
{%- block radio_widget -%}
<input type="radio" name="{{ full_name }}" id="radio_{{ value }}" value="{{ value }}"{% if checked %} checked="checked"{% endif %} />
{%- endblock radio_widget -%}
Use custom form rendering
You will just need to customize the widget_radio block using one of the techniques described in that cookbook entry

CSS for Symfony2 forms: "Hello World" equivalent

How to alter the fields.html.twig template?
I am only looking for the "hello world" equivalent to see the first ever change to the form.
What's working (within a bundle view as add.Article.html.twig):
<div class="well;">
<form method="post" {{ form_enctype(form) }}>
{{ form_widget(form,{attr: {class:'test'}} ) }}
<input type="submit" class="btn btn-primary" />
</form>
</div>
The test class is only doing a CSS .test{background-color:grey;}. I am normally using Bootstrap.
In fields.html.twig I have:
{% block aliquam_input %}
{% spaceless %}
<div>
{{ form_label(form) }}
{{ form_errors(form) }}
{{ form_widget(form, { 'attr': {'class': 'test'} }) }}
</div>
{% endspaceless %}
{% endblock %}
and in app/config/config.yml:
# Twig Configuration
twig:
//..
form:
resources:
- 'AliquamSummaryBundle:Form:fields.html.twig'
The fields.html.twig is rendered ok to the main twig as I get an error when removing one of the hash in the fields twig.
What's not working (i.e. class test doesn't show) is when I try to make the fields.html.twig take effect on Article.html.twig:
{% block aliquam_input %}
{% spaceless %}
<div class="well;">
<form method="post" {{ form_enctype(form) }}>
{{ form_widget(form) }}
<input type="submit" class="btn btn-primary" />
</form>
</div>
{% endspaceless %}
{% endblock %}
As all forms will have the same format, I'd prefer to not set all html attributes to every single line. But what is the way to get the class "test" taking effect from the fields.html.twig template?
___________________________ Update for David _____________
Thanks #David, but unfortunately adding the name as form.name doesn’t change anything. The CSS attribute is still not transferred to the form in html. Well spot for the semicolon after well; it was a late night typo, but not related to the problem.
Here is what I have figured so far. I might have to end up having to enter bootstrap CSS to each individual row in a form (horrible thought) or figure how to do this by entities options, which comes almost to the same horrible thought as doing it for every row. Since the doc offers to enter a template for all forms via app/config/config.yml there should be a far simpler way, but I don’t get it.
The below is the only direction so far which made CSS work a little, i.e. class .test{background-color: black;} is doing its job:
{# ..\addArticle.html.twig #}
<div class="well">
<form method="post" {{ form_enctype(form) }}>
{{ form_widget(form) }}
<input type="submit" class="btn btn-primary" />
</form>
</div>
NB: there is no {% block .. %} around the div, which makes sense as I put the fields.html.twig to be included to the symphony standard widgets through app/config/config.yml. The above goes with the fields.html.twig below.
{# ..\fields.html.twig #}
{% block widget_attributes %}
{% spaceless %}
{{" class=\'test\'" }}
{% endspaceless %}
{% endblock widget_attributes %}
So far only fields with textarea show black color, bit it’s kind of “hello world”. I am not sure if this is right way to proceed as I have not found anything alike in this and other forums and the doc only states to look at form_div_layout.html.twig on git to decide which attribute to change, which is not really helpful (to me).
First change your well; class to well in your add.Article.html.twig.
In order to put a class on your widget I think you can try
{{ form_widget(form.name, {'attr': {'class': 'test'}}) }}
The difference with your code is the form.name parameter. If you only give the form it will not apply passed options. See the doc
Changing the fields.html.twig as
{# ..\fields.html.twig #}
{% block widget_attributes %}
{% spaceless %}
{{" class=\'test\'" }}
{% endspaceless %}
{% endblock widget_attributes %}
is indeed correct in what concerns Symfony and the reason that with bootstrap-CSS only the textareas show the class="test" is that bootstrap assigns mandatorily (all other than textareas) with the bootstrap specific one.
As I don't want to alter the bootstrap as such I ended up assigning the attributes per widget from within the entities - anything else would probably opening a can of worms.

How to customize the submit button rendering?

I'm using symfony 2.4 and I need to set my own theme for just the submit button within a form. I was already able to customize the way input fields are rendered, the following code is working.
{% block form_row %}
{% spaceless %}
<div class="form-group">
{{ form_errors(form) }}
{{ form_label(form) }}
{{ form_widget(form, { 'attr': {'class': 'form-control'} }) }}
{% if help is defined %}
<span class="help">{{ help }}</span>
{% endif %}
</div>
{% endspaceless %}
{% endblock form_row %}
Question: Which block do I need to override to accomplish my goal?
As explained in the How to customize Form Rendering section of the documentation. The submit button related blocks that you should override in order to customise your form's button are {% block submit_widget %} and {% block button_widget %} depending on the level of customisation you want to introduce.
Check the form_div_layout.html.twig code to fully understand the default implementation of those helpers.
Good to know,
Buttons support in Forms added to Symfony 2.3.

Changing form_row

Can someone help me to tranform this line:
<li>{{ form_row(form.features_reducing_value) }}</li>
to this or something like this :
<div id="dynamicInput">
Entry 1<br><input type="text" name="myInputs[]">
</div>
<input type="button" value="Add another text input" onClick="addInput('dynamicInput');">
If I understood you correctly, you want to be able to clone your form fields. In Symfony this is done using form collections and embedding them with "prototype".
More information is here -> http://symfony.com/doc/master/cookbook/form/form_collections.html
for instance to override the <input type="number" /> you do like this:
{# src/Acme/DemoBundle/Resources/views/Form/fields.html.twig #}
{% block integer_widget %}
<div class="integer_widget">
{% set type = type|default('number') %}
{{ block('form_widget_simple') }}
</div>
{% endblock %}
And in your html.twig file you use the from_theme like this:
{% form_theme form 'AcmeDemoBundle:Form:fields.html.twig' %}
more information about that here

Twig Form Theming - form_label class attribute

I've been trying to override the form_row Twig extension so I can render a Twitter Bootstrap style row. A twitter boostrap form row should look like this:
<div class="control-group">
<label class="control-label" for="idOfMainInput">Label Name:</label>
<div class="controls">
<input type="text" id="idOfMainInput" name="someDumbName">
</div>
</div>
The base twig div style form_row block is defined in this link as below:
{% block form_row %}
{% spaceless %}
<div>
{{ form_label(form) }}
{{ form_errors(form) }}
{{ form_widget(form) }}
</div>
{% endspaceless %}
{% endblock form_row %}
So, my thoughts were to just put the necessary divs in, and hard code where necessary the class entries (i.e. in the main div) but pass the 'attr' value to the form_label, form_errors and form_widget sections. I've taken out form_errors for now, just so I don't get too deep into it. Here's what I tried:
{% form_theme form _self %}
{% block form_row %}
{% spaceless %}
<div class="control-group">
{{ form_label(form, 'test label name', { 'attr': {'class': 'control-label'} }) }}
<div class="controls">
{{ form_widget(form) }}
{{ form_errors(form) }}
</div>
</div>
{% endspaceless %}
{% endblock form_row %}
The problem, though, is no matter what I try, the form_label extension does not use "control-label" as my class (and it should according to the source code append it if there's existing ones, like "required"). Here's what I get when I view the source of the rendered page:
<div class="control-group">
<label for="form_rsa_id" class="required">test label name</label>
<div class="controls">
<input type="number" id="form_rsa_id" name="form[rsa_id]" required="required" />
</div>
</div>
As you can see, the class="required" is there and is taken from the base form object attributes, but it should be class="required control-label", which it's not.
Kinda at a loss here, as the documentation (as well as the source) states that one should use the notation "form_label(view, label, variables)". Link to docs here.
I think you need to use label_attr rather than attr.
For anyone still looking to do this, Symfony 2.6 comes with a Bootstrap form theme which will do this for you.

Resources