Twig Form Theming - form_label class attribute - symfony

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.

Related

Django crudbuilder & Bootstrap datepicker

Django==1.11.7
django-crudbuilder==0.2.5
Using Bootstrap datepicker. Now trying to use the datepicker in a crud form for a date field.
In a normal Django form, this would work:
self.fields['payment_date'].widget.attrs.update({'class': 'datepicker'})
But how can the class:datepicker be set for a particular field in a crud form?
The documentation doesn't seem to mention anything useful on css or html class.
Start with implementing custom templates.
Copy over the instance templates in crudbuilder/templates/crudbuilder/instance/ into your application template directory.
Replace the template location for the included form template in all the copied over instance templates .e.g. create.html
...
{% block main_content %}
<div class='container'>
<h3>Create {{actual_model_name|title}}</h3>
<hr/>
{% include "my_app/widgets/form.html" %}
</div>
{% endblock %}
In my_app/templates/my_app/widgets/form.html, write this instead to set the datepicker class on payment_date. (Original code was copied from django-cruid)
{% load crudbuilder %}
{% include "datepicker.html" %}
<form action="." method="post" enctype="multipart/form-data" class="form-horizontal" novalidate>
{% csrf_token %}
{% for field in form %}
<fieldset class={% if field.errors %} "form-group has-error" {% else %} "form-group" {% endif %} >
{{ field|label_with_class:"col-sm-2 control-label" }}
<div class="col-xs-4">
{% if field.name == 'payment_date' %}
{{ field|input_with_class:"form-control datepicker" }}
{% endif %}
{{ field|input_with_class:"form-control" }}
{{ field.errors }}
</div>
</fieldset>
{% endfor %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-12">
<input type="submit" value="Save" class="btn btn-success" />
</div>
</div>
</form>
Finally, set your crud form to use your custom templates.
class PersonCrud(BaseCrudBuilder):
...
custom_templates = {
'list': 'my_app/list.html',
'create': 'my_app/create.html',
'detail': 'my_app/detail.html',
'update': 'my_app/update.html',
'delete': 'my_app/delete.html'
}

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 -%}

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.

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

Getting form widget name in Symfony2/Twig

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 }}

Resources