Symfony2 choice form split in twig - forms

OK so i have a choice form with 2 options
$builder->add('type', 'choice', array(
'label' => 'User type',
'choices' => array('1' => 'Customer', '2' => 'Supplier'),
'expanded' => true,
'multiple' => false,
'required' => false,
));
And i want to split options in view using twig to get something like this:
{{ form_widget(form.type/choice_1/) }}
some html stuf
{{ form_widget(form.type/choice_2/) }}
Any sugestions?

You need to add template to the form. Here's the docs:
http://symfony.com/doc/current/cookbook/form/form_customization.html
Here you got multiple examples:
https://github.com/phiamo/MopaBootstrapBundle/blob/master/Resources/views/Form/fields.html.twig
This field is for you:
{% block choice_widget_expanded %}
{% spaceless %}
<div {{ block('widget_container_attributes') }}>
{% for child in form %}
<label class="{{ (multiple ? 'checkbox' : 'radio') ~ (widget_type ? ' ' ~ widget_type : '') ~ (inline is defined and inline ? ' inline' : '') }}">
{{ form_widget(child, {'attr': {'class': attr.widget_class|default('')}}) }}
{{ child.vars.label|trans({}, translation_domain) }}
</label>
{% endfor %}
</div>
{% endspaceless %}
{% endblock choice_widget_expanded %}
You can do whatever you want just leave the: {{ form_widget(child, {'attr': {'class': attr.widget_class|default('')}}) }} alone :)
You need to create file YourBundle/Resources/Form/fields.html.twig
Paste there the code above.
Add theming to the form: {% form_theme form 'AcmeDemoBundle:Form:fields.html.twig' %}
And be ready to rock'n'roll!

Defined number of fields:
{{ form_widget(form.type.0) }}{{ form_label(form.type.0) }}
some html stuf
{{ form_widget(form.type.1) }}{{ form_label(form.type.0) }}
A variable number of fields:
{% for i in 0..form.type|length-1 %}
{{ form_widget(form.type[i]) }}
{{ form_label(form.type[i]) }}
{% endfor %}
And when we have id in choice not in order:
e.g
$typeChoice = [
"choice 1" => 2,
"choice 2" => 5
]
{% for type in form.type %}
{{ form_label(type) }}
{{ form_widget(type) }}
{% endfor %}

Related

How can I remove form-control class?

I need to remove the form-control class on an element of a form because it applies padding. This class is automatically added when creating the form.
And I don't want padding on any of these form lines...But how to do it ?
Here is my code :
Form : only the part of the form on which I don't want "form-control" class.
->add('progress', RangeType::class, [
'label' => 'kpi.form.progress',
'attr' => [
'min' => 0,
'max' => 100,
],
])
Twig :
{% for formTeamOKR in formCompanyOKR.teamOKRs %}
{% for formKPI in formTeamOKR.KPIs %}
{% if formKPI.vars.data.id == kpi.id %}
{{ form_row(formKPI) }}
{% endif %}
{% endfor %}
{% endfor %}
I tried to use this :
How to prevent Twig from adding form-control class to the fields it generates?
and this : Symfony Add bootstrap form-control class
and to add this in my twig :
{% set attr = {class: (attr.class|default(''))|trim} %}
just before :
{{ form_row(formKPI) }}
Thanks!!!

Variable "captcha_code" does not exist Gregwar

everybody i'm trying to add a captcha to my form with Gregwar/CaptchaBundle but i face a probleme :
Variable "captcha_code" does not exist when i pay this part of my code :
========================================================================
<div class="col-sm-8 col-sm-offset-2">
{% block captcha_widget %}
{% spaceless %}
<img src="{{ captcha_code }}" title="captcha" width="{{ captcha_width }}" height="{{ captcha_height }}" />
{{ form_row(form.captcha) }}
{% endspaceless %}
{% endblock %}
</div>
Variable form inside of widget block already contains the captcha field (not the whole form), so the correct way is to use form_widget(form) instead of form_row(form.captcha) :
{% block captcha_widget %}
{% spaceless %}
<img src="{{ captcha_code }}" title="captcha" width="{{ captcha_width }}" height="{{ captcha_height }}" />
{{ form_widget(form) }}
{% endspaceless %}
{% endblock %}
thank you but i figured out it by myselfe the best way to solve my problem was to
configure captcha field in my form builder
$builder->add('captcha', 'Gregwar\CaptchaBundle\Type\CaptchaType',array(
'width' => 200,
'height' => 50,
'length' => 6,
'quality' => 90,
'distortion' => true,
'background_color' => [115, 194, 251],
'max_front_lines' => 0,
'max_behind_lines' => 0,
'attr' => array('class' => 'form-control',
'rows'=> "6"
)
));
and in my twig template only call this small part of code :
<div class="col-sm-8 col-sm-offset-2">
{% block captcha_widget %}
{% spaceless %}
{{ form_row(form.captcha) }}
{% endspaceless %}
{% endblock %}
</div>

Symfony-Twig: insert fontawesome icon in a form_widget

To validate a form I am using a standard:
{{ form_widget(form.save, {'attr': {'class': 'btn btn-sm btn-danger'}, 'label': 'Submit form'}) }}
I want to insert a fontawsome icon in the button. I tried:
{{ form_widget(form.save, {'attr': {'class': 'btn btn-sm btn-danger'}, 'label': '<i class="fa fa-envelope-o"></i> Submit form'}) }}
But it is not working; obviously
Any idea how to that?
I would define a new form template in the same view (or in a template if you need to reuse the code). More details here
{% extends '::base.html.twig' %}
{% form_theme form _self %}
{%- block submit_widget -%}
{%- set type = type|default('submit') -%}
{%- 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 -%}
<button type="{{ type|default('button') }}" {{ block('button_attributes') }}>
<i class="fa fa-envelope-o"></i>
{{ label|trans({}, translation_domain) }}
</button>
{%- endblock submit_widget -%}
{% block content %}
{# ... render the form #}
{{ form_row(form.age) }}
{% endblock %}
EDIT
You can also extend ButtonType to allow icon_before and icon_after in order to add icons easily in form definition :
$form->add('submitReportV2Show', SubmitType::class, array(
'label' => 'My test',
'icon_before' => 'fa-refresh',
'icon_after' => 'fa-refresh',
'attr' => array('class' => 'btn btn-sm btn-success'
)));
Create a new class src/bundle/Form/Extension:
namespace YourBundle\ToolBoxBundle\Form\Extension;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Core\Type\ButtonType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
class IconButtonExtension extends AbstractTypeExtension
{
public function getExtendedType()
{
return ButtonType::class;
}
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->vars['icon_before'] = $options['icon_before'] ?? '';
$view->vars['icon_after'] = $options['icon_after'] ?? '';
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'icon_before' => null,
'icon_after' => null
]);
}
}
Declare it in service src/bundle/Resources/config/service.yml
bundle.tools.form.type_extension.icon_button:
class: YourBundle\ToolBoxBundle\Form\Extension\IconButtonExtension
tags:
- { name: 'form.type_extension', extended_type: 'Symfony\Component\Form\Extension\Core\Type\ButtonType' }
app/Resources/views/Form/fields.html.twig
{%- block button_widget -%}
{%- if label is empty -%}
{%- if label_format is not empty -%}
{% set label = label_format|replace({
'%name%': name,
'%id%': id,
}) %}
{%- elseif label is same as(false) -%}
{% set translation_domain = false %}
{%- else -%}
{% set label = name|humanize %}
{%- endif -%}
{%- endif -%}
<button type="{{ type|default('button') }}" {{ block('button_attributes') }}>
{% if icon_before is defined and icon_before is not null %}
<i class="fa {{ icon_before }}"></i>
{% endif %}
{{ translation_domain is same as(false) ? label : label|trans({}, translation_domain) }}
{% if icon_after is defined and icon_after is not null %}
<i class="fa {{ icon_after }}"></i>
{% endif %}
</button>
{%- endblock button_widget -%}
sdespont's answer is the correct answer and worthy of being selected. I have, however, extended the functionality of it to include adding the custom fa class icon as well as whether the icon is placed to the left or right of the button text.
Since this functionality accepts variables the best thing to do is to create a template to be reused instead of customising just the view.
Form template: app/Resources/views/form/submit.html.twig
{# app/Resources/views/form/submit.html.twig #}
{% block submit_widget %}
{% set type = type|default('submit') %}
{% 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 %}
<button type="{{ type|default('button') }}" {{ block('button_attributes') }}>
{% if fa is defined %}
{% if left is defined and left %}
<i class="fa {{ fa }}"></i>
{% endif %}
{{ translation_domain is same as(false) ? label : label|trans({}, translation_domain) }}
{% if right is defined and right %}
<i class="fa {{ fa }}"></i>
{% endif %}
{% else %}
{{ translation_domain is same as(false) ? label : label|trans({}, translation_domain) }}
{% endif %}
</button>
{% endblock submit_widget %}
Controller:
$form = $this->createFormBuilder($user)
...
->add('submit', SubmitType::class, array(
'attr'=> array('class'=>'myclass')
))
->getForm();
Twig template:
{{ form_widget(form.submit, {'fa' : 'fa-long-arrow-right','right' : true}) }}
You can set any old fa icon and even sizing like so: fa-long-arrow-right fa-2x
The easiest, you can put your button with html and form vars:
<button type="submit" name="{{ form.send.vars.full_name }}" id="{{ form.send.vars.id }}" class="btn btn-sm btn-danger"><i class="fa fa-envelope-o"></i></button><
You can just add a new custom service css class per icon
/*
* css selector for a class attribute that starts with "btn-fa-" or has " btn-fa-" in it:
*/
[class^="btn-fa-"]:before,
[class*=" btn-fa-"]:before
{
font-family: "Font Awesome 5 Free";
font-weight: bold;
margin: 0 6px 0 2px;
}
/*
* And then only 1 setting per font awesome class
*/
.btn-fa-plus:before {
content: '\f067';
}
And add the class to the ButtonType
->add('Add an item', ButtonType::class, [
'attr' => [
'class' => 'btn btn-primary btn-fa-plus',
]
])
In YourFormType.class -> buildForm
->add('submit', SubmitType::class, [
'attr' => [
'class' => 'main-btn primary-btn',
],
'label' => '<i class="fas fa-search"></i> Search',
'label_html' => true,
])

Symfony2 form layout - variables source

Here's the main form layout twig file:
https://github.com/symfony/symfony/blob/master/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig
An example:
{% block form_widget_simple %}
{% spaceless %}
{% set type = type|default('text') %}
<input type="{{ type }}" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %}/>
{% endspaceless %}
{% endblock form_widget_simple %}
I wonder where varaibles like "type" or "value" come from?
The goal I'm trying to achieve is to set form row's label as a placeholder in the widget. How can I accomplish this?
Details how to override Template for Form field you will find here.
If you trying to change labels to placeholders all you need is to change way of rendering your forms. Remove form_widget(form) and switch to render every separate form field:
{# ... #}
<div class="form-group">
{{ form_errors(form.email) }}
{{ form_widget(form.email, {'attr': {'class': 'form-control', 'placeholder': 'E-mail address'|trans }}) }}
</div>
{# ... #}
This example generate input for email field and html/css classes for bootstrap.
And shows you how {{ type }} and {{ value }} are passed - by attr array.
Good Luck!

symfony 2 form_row with 2 fields

I need something like below:
{% block form_row %}
<div class="form_row">
{{ form_label(form) }}
{{ form_widget(form) }}
{{ form_widget(form.field_name + '_previous') }}
{{ form_errors(form) }}
</div>
{% endblock form_row %}
i.e, two form fields in one row; second field name is equal to first_field_name + _previous.
For example, if field name is 'total_cost', then second field will be 'total_cost_previous'.
How can I do that?
i think you can do something like this:
{% set field = field_name ~ '_previous' %}
{{ form_widget(attribute(form, field)) }}