I want to render raw form label, I have the following form entity type
$builder
->add('subscriptionBilling', 'entity', array(
'class' => 'AppBundle\Entity\SubscriptionBilling',
'data_class' => 'AppBundle\Entity\SubscriptionBilling',
'choice_label' => function ($allChoices, $currentChoiceKey) {
return '<p>Categories <strong>'.$allChoices->getNoOfCategories().' number</strong> '.$currentChoiceKey.'</p>';
},
'choices' => $options['packages_allowed'],
'data' => $options['selected_subscriptionBilling'],
'multiple' => false,
'expanded' => true,
'required' => true,
'label' => false,
))
;
and my twig
{% autoescape false %}
{{form_label(form_categories.subscription.subscriptionBilling)|raw}}
{{form_widget(form_categories.subscription.subscriptionBilling)|raw}}
{% endautoescape %}
but i get this html
<p>Categories <strong>5 number</strong> 0</p>
<p>Categories <strong>10 number</strong> 1</p>
<p>Categories <strong>25 number</strong> 2</p>
<p>Categories <strong>10 number</strong> 3</p>
I finally created a form theme which extends bootstrap form layout
{% extends 'bootstrap_3_layout.html.twig' %}
{% block 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 %}
{% set label = name|humanize %}
{% 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|raw : label|trans({}, translation_domain)|raw ) -}}
</label>
{% endif %}
{% endblock radio_label %}
and my twig
{% autoescape %}
{{form_label(form_categories.subscription.subscriptionBilling)}}
{{form_widget(form_categories.subscription.subscriptionBilling)}}
{% endautoescape %}
and it seems to work
Related
I'm trying to customize the rendering of the File Input in Symfony with twig.
plugins.krajee.com/file-basic-usage-demo
I follow the documentation : https://symfony.com/doc/current/form/form_customization.html
In my config.yml
# Twig Configuration
twig:
form_themes:
- 'bootstrap_3_layout.html.twig'
I try all methode...
1) Custome inside the the view in my view.html.twig (this is a copy past of the existing bootstrap layout, I just add class="file")
{% form_theme form _self %}
{% block _user_file_widget -%}
{% if type is not defined or type not in ['file', 'hidden'] %}
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-control')|trim}) -%}
{% endif %}
{%- set type = type|default('text') -%}
<input class="file" type="file" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %}/>
{%- endblock _user_file_widget %}
And in my FileType
$builder->add('imageFile', FileType::class, array(
'required' => false,
'label' =>false,
'block_name' => 'file',
));
That gives me an error
The merge filter only works with arrays or "Traversable", got "NULL" as first argument.
2) Create an external file
In Ressources/View/Form/fields.html.twig
{% block form_widget_simple -%}
{% if type is not defined or type not in ['file', 'hidden'] %}
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-control')|trim}) -%}
{% endif %}
{%- set type = type|default('text') -%}
<input class="file" type="file" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %}/>
{%- endblock form_widget_simple %}
And in the view
{% form_theme form 'form/fields.html.twig' %}
But all fields are customized...
3) Add class in the rendering in the view
{{ form_widget(form.imageFile, {'attr': {'class': 'file', 'type': 'file'} }) }}
And for this 2 last methods I get this:
I am open to all solution !
Thank you for your help.
I found it !
It's working as I want using kartik-v/bootstrap-fileinput.
After installation, I add some assetic in my config.yml
kartik_js:
inputs:
- "%kernel.root_dir%/../vendor/kartik-v/bootstrap-fileinput/js/fileinput.js"
- "%kernel.root_dir%/../vendor/kartik-v/bootstrap-fileinput/js/locales/fr.js"
- "%kernel.root_dir%/../vendor/kartik-v/bootstrap-fileinput/themes/explorer/theme.js"
kartik_css:
inputs:
- "%kernel.root_dir%/../vendor/kartik-v/bootstrap-fileinput/css/fileinput.min.css"
- "%kernel.root_dir%/../vendor/kartik-v/bootstrap-fileinput/themes/explorer/theme.css"
Then in the view I add the css and js
{% block stylesheets %}
{{ parent() }}
{% stylesheets '#kartik_css' combine=true %}
<link href="{{ asset_url }}" type="text/css" rel="stylesheet" />
{% endstylesheets %}
{% endblock %}
{% javascripts '#kartik_js' combine=true %}
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
The form widget
{{ form_widget(form.imageFile)}}
And the Javascrip
$("#fos_user_profile_form_imageFile").fileinput({
language: 'fr',
showUpload: false,
allowedFileExtensions: ['jpg', 'png', 'gif']
});
The Result !
Is Amazing
I hope this will help some one :)
Have a good day !
I am fighting with customize on symfony forms for twig...
My problem is to add html inside a label for a radio button like <strong>25</strong> but it is escaped by default and I can't find how to unescape. I use the following code.
{% block choice_widget %}
{%
set labels = {
1: { title: '1 ' ~ 'label.credits'|trans ~ ' - <strong>1€</strong>' },
2: { title: '2 ' ~ 'label.credits'|trans ~ ' - <strong>2€</strong>' },
25: { title: '25 ' ~ 'label.credits'|trans ~ ' - <strong>25€</strong>' },
}
%}
<div {{ block('widget_container_attributes') }}>
{% for child in form %}
{% if child.vars.value matches '/^[1|2|25]{1}/' %}
{% set currentLabel = labels[child.vars.value].title %}
{% else %}
{% set currentLabel = '' %}
{% endif %}
{{ form_widget(child, {'label': currentLabel}) }}
{{ form_label(child) }}
{{ form_errors(child) }}
{% endfor %}
</div>
{% endblock %}
In your case you will need to override the form_label block and incorporate into your own theme (https://symfony.com/doc/current/form/form_customization.html), this is for bootstrap 4 (find the file in vendors folder called bootstrap_4_layout.html.twig, if you need this for bootstrap 3 just do the same but the file is bootstrap_3_layout.html.twig), notice where I've inserted the <strong> and </strong> tags:
{% block form_label -%}
{% if label is not same as(false) -%}
{%- if compound is defined and compound -%}
{%- set element = 'legend' -%}
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' col-form-label')|trim}) -%}
{%- else -%}
{%- 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 -%}
<{{ element|default('label') }}{% if label_attr %}{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}{% endif %}><strong>{{ translation_domain is same as(false) ? label : label|trans({}, translation_domain) }}</strong>{% block form_label_errors %}{{- form_errors(form) -}}{% endblock form_label_errors %}</{{ element|default('label') }}>
{%- else -%}
{%- if errors|length > 0 -%}
<div id="{{ id }}_errors" class="mb-2">
{{- form_errors(form) -}}
</div>
{%- endif -%}
{%- endif -%}
{%- endblock form_label %}
You can try the above by putting it in the actual twig view and putting this statement above it:
{% form_theme form _self %}
Extra (for a checbkox): To achieve this for a checkbox you will need to override the label template, pull out the block for
{% block checkbox_radio_label -%} from bootstrap_4_layout.html.twig or bootstrap_3_layout.html.twig and then incorporate this into your own theme.
Extra extra (for a checkbox): If you also need to customise the widget, pull out the block for {% block checkbox_widget -%} i.e. remove the label rendering from within it (yes, for some internal reason the widget generates the label as well) and customise the way you want it to be. This way even calling form_label on a checkbox will output the label (otherwise form_label will not output anything)
Look here : http://symfony.com/doc/current/reference/forms/types/choice.html#select-tag-checkboxes-or-radio-buttons
You can put the parameter expanded to true and multiple to false in your formType for have radio buttons in your html
I have a form twig template with helpers and form blocks which I want to use to automatically style my form in the way Zurb Foundations expects.
It seems to be working well mostly but I have run into an issue with choice expanded (radio buttons) as you can see below.
Here is the generate markup:
<div class="large-12 columns">
<input type="radio" id="user_gender_0" name="user[gender]" required="required" class="" value="male"> <label class="is-required">Male<input type="radio" id="user_gender_1" name="user[gender]" required="required" class="" value="female"> <label class="is-required">Female</label></label>
</div>
For some reason the label for the "Male" option is wrapping the "Female" option and when corrected in inspect element it's fine.
Here is my twig template where I override blocks:
{#
############# Radio #############
#}
{%- block radio_widget -%}
<input type="radio" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />
{%- endblock radio_widget -%}
{#
############# Labels #############
#}
{%- block form_label -%}
{% if label is not sameas(false) -%}
{% if required -%}
{% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' is-required')|trim}) %}
{%- endif %}
{% if errors|length > 0 -%}
{% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' error')|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 %}>{{ label|trans({}, translation_domain) }}
{%- endif -%}
{%- endblock form_label -%}
{%- block button_label -%}{%- endblock -%}
Updated info, the form type option:
->add('gender', 'choice', [
'constraints' => new NotBlank(),
'choices' => Profile::getGenderTypes(),
'expanded' => true,
'multiple' => false,
'mapped' => false,
'attr' => [
'data-user-form' => 'gender'
]
])
Can anyone suggest a better layout to match Foundation 5 Forms.
Kindest Regards
Nathan
In this line
<label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>{{ label|trans({}, translation_domain) }}
You didn't close the label tag. That's why the Male label is wrapping the Female option.
Solution
Add </label> at the end.
<label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>{{ label|trans({}, translation_domain) }}</label>
I made select form in buildForm()
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('icon','entity',
array(
'class' => 'UserBundle:IconPics',
'property' => 'label',
'expanded' => true,
'data' => $defaultIcon,
'multiple' => false,
'label' => 'form.icon',
'query_builder' => function ($repository) {
return $repository->createQueryBuilder('i')
->add('where', 'i.enabled = true');
},
));
in twig.
{{ form_widget(form.icon) }}
it shows the radiobutton selector html like this.
<div id="fos_user_registration_form_icon">
<input type="radio" id="fos_user_registration_form_icon_3" name="fos_user_registration_form[icon]" required="required" value="3" checked="checked" />
<label for="fos_user_registration_form_icon_3" class="required">male</label>
<input type="radio" id="fos_user_registration_form_icon_4" name="fos_user_registration_form[icon]" required="required" value="4" />
<label for="fos_user_registration_form_icon_4" class="required">female</label>
<input type="radio" id="fos_user_registration_form_icon_5" name="fos_user_registration_form[icon]" required="required" value="5" />
<label for="fos_user_registration_form_icon_5" class="required">old male</label>
<input type="radio" id="fos_user_registration_form_icon_6" name="fos_user_registration_form[icon]" required="required" value="6" />
</div>
However,this html is not cool,just align the radio button.
I would like to design this html.
such as using table or something
<table><tr>
<td>Button1</td>
<td>label</td>
</tr></table>
Is it possible?
Thanks for your reply
I have read the link and choose the most simple way.
put this at the top of twig and made some progress.
But I am facing two problems
{% form_theme form _self %}
{% block radio_widget %}
<td>
<input type="radio" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}/>
</td>
{% endblock radio_widget %}
it shows the html like this
<td style="border-style:none;">
<input type="radio" id="fos_user_registration_form_icon_3" name="fos_user_registration_form[icon]" required="required" value="3"/></td>
<label for="fos_user_registration_form_icon_3" class="required">male</label>
1.problem
radio button is inside the td tag (good!!),but label is out side the
where does this label appears?????
how can I delete or control this???
I understood this label is defferent from the 'label' that I can choose at the formBuilder.
2) problem
when I use 'checked' as sample says
{% if checked %} checked="checked"{% endif %}
it says like this checked property is used in even normal
form_div_layout.html.twig
I have no clue about this.
Please help me . thanks
Variable "checked" does not exist in FOSUserBundle:Registration:register_content.html.twig at line 7
500 Internal Server Error - Twig_Error_Runtime
You can override the form theme in twig by using your new form layout like
{% form_theme formObject 'NamespaceYourBundle:Form:form_div_layout.html.twig' %}
and in form_div_layout.html.twig redefine your field blocks like for radio button you can customize it
{% block radio_widget %}
{% spaceless %}
<td>
<input type="radio" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />
</td>
{% endspaceless %}
{% endblock radio_widget %}
For label block you can use it like
{% block form_label %}
{% 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 %}
And now finally override the expanded widget
{% 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 %}
Edit 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 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 %}
How to customize Form Rendering
Check out Form theming.
You have to create fields.html.twig and include into yout twig file like:
{% form_theme form with 'AcmeTaskBundle:Form:fields.html.twig' %}
In fileds.html.twig add radio widget (check out). Here you can now add tables, divs etc. Inside {% block radio_widget %}.
{% block radio_widget %}
{% spaceless %}
<input type="radio" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />
{% endspaceless %}
{% endblock radio_widget %}
I am playing with Symfony's form builder, and I can't find a way to not display a label. Further, I am interested in actually setting a placeholder for each input box. Is this possible? I have researched a bit and found nothing.
My form:
<form action="{{ path('searchPeople') }}" method="post" class="form-inline">
{{ form_errors(form) }}
{{ form_row(form.first_name) }}
{{ form_row(form.last_name) }}
{{ form_rest(form) }}
<br />
<button type="submit" class="btn btn-primary" /><i class="icon-search"></i>Search</button>
</form>
I know it's already answered, but might help somebody who is looking for a different solution for placeholders, if you don't want to change anything in your twig template:
$builder->add(
'name',
'text',
array(
'attr' => array(
'placeholder' => 'Your name',
),
'label' => false,
)
);
If you're outputting the field with form_rest you'll have to set the label for the the field to false in the form builder with something like
$builder->add('first_name', 'text', array(
'label' => false,
));
If you output the fields individually, you can omit the form_label for that field in the twig template, or set it to an empty string.
{{ form_label(form.first_name, '') }}
Convert label to placeholder
{% use 'form_div_layout.html.twig' with widget_attributes as base_widget_attributes %}
{% block widget_attributes %}
{% set attr = {'placeholder': label|trans({}, translation_domain)} %}
{{- block('base_widget_attributes') -}}
{% endblock widget_attributes %}
I did this recently! :) You'll want to create a new fields template, for form_row and one for form_widget. Then remove the form_label part, and add your placeholder.
http://symfony.com/doc/current/cookbook/form/form_customization.html
You can do it per field, or set it for all of them.
Or you can also skip the removing the form_label from the form_row template, and just do form_widget() where you're currently calling form_row()
for other that come across this label-question:
you could use form theme to override the form_row tag for every form you want. However I recommend to just set it invisible for page reader optimization. my example with bootstrap:
{% block form_row %}
{% spaceless %}
{{ form_label(form, null, {'label_attr': {'class': 'sr-only'}}) }}
{{ form_errors(form) }}
{{ form_widget(form) }}
{% endspaceless %}
{% endblock form_row %}
don't forget to include your formtheme in config.yml and template.
For those NOT using form_row, you can always add the placeholder as an attribute directly when adding the input to the builder. Like so:
$task = new Task();
$form = $this->createFormBuilder($task)
->add('first_name', 'text', array(
'required' => true,
'trim' => true,
'attr' => array('placeholder' => 'Lorem Ipsum')
)->getForm();
Symfony 2.8 & above
Remove form_label
{% block form_row %}
<div>
{{ form_errors(form) }}
{{ form_widget(form) }}
</div>
{% endblock form_row %}
Add placeholder attribute
{% block form_widget_simple %}
{% set type = type|default('text') %}
<input placeholder="{{ translation_domain is same as(false) ? label : label|trans({}, translation_domain) }}" type="{{ type }}" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %}/>
{% endblock form_widget_simple %}
Expanding on Léo's answer:
{% use 'form_div_layout.html.twig' %}
{% block widget_attributes %}
{% spaceless %}
{% set attr = attr|merge({'placeholder': label}) %}
{{ parent() }}
{% endspaceless %}
{% endblock widget_attributes %}
trans filter has been removed because it is included in the parent.
You must render the form manually.
Here's an example:
<form id="form-message" action="{{ path('home') }}" method="post" {{ form_enctype(form) }}>
{{ form_label(form.name) }}
{% if form_errors(form.name) %}
<div class="alert alert-error">
{{ form_errors(form.name) }}
</div>
{% endif %}
{{ form_widget(form.name) }}
{{ form_row(form._token) }}
<input type="submit" class="btn" value="Submit">
</form>
Related documentation
To sums it up:
Titi's answer is the most simple ;
Mick, Léo & Quolonel's answers are the most effective but are incomplete (for symfony > 2.6) :
If you use the label_format option in your *Type::configureOptions, their solution does not work. You need to add the content of the form_label block to handle all the label possibilities.
The full & most effective answer (code used w/ symfony 3.3) :
Remove form_label
{% block form_row %}
<div>
{{ form_errors(form) }}
{{ form_widget(form) }}
</div>
{% endblock form_row %}
Edit the widget_attribute block
{% block widget_attributes %}
{% spaceless %}
{% if label is not same as(false) -%}
{% 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 -%}
{% set attr = attr|merge({'placeholder': label}) %}
{%- endif -%}
{{ parent() }}
{% endspaceless %}
{% endblock widget_attributes %}
Notes :
Do not translate the labels into the widget_attributes block, otherwise they will appear as missing translations.
The solution does not work for checkboxes or radio buttons, you'll want to add something like :
{%- block checkbox_widget -%}
{{ parent() }}
{{- form_label(form) -}}
{%- endblock checkbox_widget -%}
Bootstrap Forms
In my case best is mix aswers of #Cethy and #Quolonel Questions
{% form_theme form _self %}
{% use 'bootstrap_4_layout.html.twig' %}
{% block widget_attributes %} {# set placeholder #}
{% spaceless %}
{% set attr = attr|merge({'placeholder': label}) %}
{{ parent() }}
{% endspaceless %}
{% endblock widget_attributes %}
{% block form_row %} {# remove label #}
<div class="form-group">
{{ form_errors(form) }}
{{ form_widget(form) }}
</div>
{% endblock form_row %}
It looks the following
It works with translations
You can also copy the labels into the placeholder attribute before rendering the form:
$formView = $form->createView();
foreach($formView->getIterator() as $item) {
/** #var $item FormView */
if ($item->vars['label']) {
$item->vars['attr']['placeholder'] =$item->vars['label'];
}
}