add html class value with existing class in symfony2 form? - forms

I have defined some filed in my FormType and each form element has class value like below
$builder->add('name', 'text', array(
'label' => 'Name',
'attr' => array('class' => 'form-control'),
));
in twig file wrote like this
{{ form_widget(form.name) }}
This code generate output like this
<input type='text' name='name' class='form-control' />
now I want to add extra class in this element like error class which generate following output
<input type='text' name='name' class='form-control error' />
For generating above output I wrote like code in Twig file-
{{ form_widget(form.name,{attr:('class'=>'error')}) }}
This code generate following output--
<input type='text' name='name' class='error' />
So I am confused, what should to get my expected result. Add extra class value to my form element in html.
My Expected output is
<input type='text' name='name' class='form-control error' />

You can add multiple classes inside the class attribute.
Like this:
$builder->add('name', 'text', array(
'label' => 'Name',
'attr' => array('class' => 'form-control error'),
));

Going by your comment on #Moshikaro's answer, you're probably going to have to use flow control to build up the class string, either in Twig or the Controller:
Twig
{% set errorClass = '' %}
{% if errorTest %}
{% set extraClass = ' error' %}
{% endif %}
{{ form_widget(form.name,{attr:('class'=>'form-control'~errorClass)}) }}
or maybe
{% set errorClass = '' %}
{% if errorTest %}
{% extraClass = ' error' %}
{% endif %}
{{ form_widget(form.name,{attr:('class'=>form.config.attributes.class~errorClass)}) }}
Controller
$errorClass = "";
if ($test)
{
$errorClass += " error";
}
$cssClasses = "form-control" + $errorClass;
$builder->add('name', 'text', array(
'label' => 'Name',
'attr' => array('class' => $cssClasses),
));
You get the idea, anyway. I've not been able to test any of that.

Related

Why does Symfony 3.4 form displays EntityType choices with label although 'label' => false was used?

I am working on an existing Symfony 3.4 based project and trying to add and render a new form. Although the 'label' => false option was used, the fields are rendered including a label. Why?
// Symfony
class SomeController extends Controller {
public function userListAction(Request $request) {
$users = $someService->getUsers();
$formBuilder = $this->createFormBuilder()
->add('users', EntityType::class, [
'label' => false, // also tested '' and 'someLabel'
'class' => 'AppBundle:User',
'choices' => $users,
'multiple' => true,
'expanded' => true,
]);
$variables = array(
'form' => $formBuilder->getForm()->createView(),
);
return $this->render('AppBundle:Pages:user_list.html.twig', $variables);
}
}
// Twig
{% extends 'AppBundle::layout.html.twig' %}
{% block page_content %}
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
{% endblock %}
This shows a list of checkboxes for all users including the username as label.
Where does Symfony get the information to use the username as label? As far as I know no custom form widget was defined for the User class. Is there any way to check this for sure? Maybe there is something hidden in the vendor bundles like FOSUserBundle?
Why is the 'label' => false option ignored?
Edit:
Different ways of rendering the form does not solve the problem:
{{ form_start(form) }}
{{ form_row(form) }}
{{ form_end(form) }}
Result:
<div id="form_users">
<div class="form-group">
<div class="checkbox">
<label for="form_users_547">
<input type="checkbox" id="form_users_547" name="form[users][]" value="547">
someUserName
</label>
</div>
</div>
</div>
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
Result:
<div id="form_users">
<div class="checkbox">
<label for="form_users_547">
<input type="checkbox" id="form_users_547" name="form[users][]" value="547">
someUserName
</label>
</div>
</div>
{{ form_start(form) }}
{% for userFormView in form.users %}
{{ form_row(userFormView) }}
{% endfor %}
{{ form_end(form) }}
Result:
Basically the same as before with form_row
You need to use ‘choice_label’ => ‘YOUR PROPERTY PATH’ in the field options.
Pretty match is written in the docs: https://symfony.com/doc/current/reference/forms/types/entity.html#choice-label
If the entity class cast to string then is used if is not it will throw an exception. It looks like your entity User cast to the user name and that’s why it works.
You should try to use {{ form_row(form) }} which should render the whole field correctly.

Symfony4 twig form - Customize / override form widget for radio button

I like to change the radio button alignment from vertical to horizontal. I knew i have to add 'form-check-inline' into the existing code <class = "form-check"> for it to happen.
Here are the conditions:
I used bootstrap_4_layout.html.twig as the base theme.
My FormType is :
->add('roles', ChoiceType::class, array(
'choices' => array(
'ADMIN' => 'ROLE_ADMIN',
'TEACHER' => 'ROLE_TEACHER',
),
'expanded' =>true,
'multiple' =>false
))
->get('roles')
->addModelTransformer(new CallbackTransformer(
function ($tagsAsArray) {
// transform the array to a string
return implode(', ', $tagsAsArray);
},
function ($tagsAsString) {
// transform the string back to an array
return explode(', ', $tagsAsString);
}
))
I already looked into form_div_layout.html.twig but I didn't know
which block to choose or how to customize/override it :
{%- block radio_widget -%}
{%- block widget_attributes -%}
{% block attributes -%}
I can arrange it use 'attr' in twig but it create a new <class> instead of overriding it :
{{ form_widget(form.roles, { 'attr': { 'class': 'form-check form-check inline'}}) }}
resulted :
<div id="task_type_transformer_roles" class="form-check form-check-inline">
<div class="form-check">
<input type="radio" id="task_type_transformer_roles_0" name="task_type_transformer[roles]" required="required" class="form-check-input" value="ROLE_ADMIN" />
<label class="form-check-label required" for="task_type_transformer_roles_0">ADMIN</label>
</div>
Thanks in advance.

Symfony form how to add class to form group

Using:
->add('name', TextType::class, [
'label' => 'Name',
'required' => true,
'attr' => [
'class' => 'myclass'
],
])
I'm adding the class "myclass" to the <input> element, getting:
<div class="form-group">
<label ...>Name</label>
<input type="text" required="required" class="myclass" ...>
</div>
What if I wanted to add the "myclass" class not to the input itself, but to its <div class="form-group"> container, in order to get:
<div class="form-group myclass">
<label ...>Name</label>
<input type="text" required="required" ...>
</div>
What's the best way to accomplish that?
I actually found a way of doing it in PHP (Symfony 4.4.2). Class has to go into 'row_attr' instead of 'attr'. For the given example it'd be:
->add('name', TextType::class, [
'label' => 'Name',
'required' => true,
'row_attr' => [
'class' => 'myclass'
],
])
related docs: https://symfony.com/doc/current/reference/forms/types/text.html#row-attr
In my case I needed to override the form_row block:
{% block form_row -%}
<div class="form-group myclass{% if (not compound or force_error|default(false)) and not valid %} has-error{% endif %}">
{{- form_label(form) -}}
{{- form_widget(form) -}}
{{- form_errors(form) -}}
</div>
{%- endblock form_row %}
as suggested, the docs helps to understand why.
As #Yoshi pointed out, in the form definition itself you cannot add classes to the container div.
The right way to customize form rendering is to override the base block via Twig as explained here: http://symfony.com/doc/current/cookbook/form/form_customization.html#how-to-customize-an-individual-field (BTW I suggest you to read carefully the whole article to know everything you need to know about customizations).
In the overridden block you have also the widget data if you want e.g. to add a class with the field id:
{% block _product_name_widget %}
<div class="text_widget {{ id }}">
{{ block('form_widget_simple') }}
</div>
{% endblock %}
in this example above, {{ id }} will be replaced with the widget (field) id.

I can not send a variable to a twig template

I dont know why not can show a variable, I read the manual and I searched in many websites, but I have no idea what I'm doing wrong...
I have a classType (there is not from a entity), the class form have 3 combobox and a textbox, when I submit the form, another template (show2.html.twig) render the new form where I want show the textbox value... I speend many time and a have 0 result ;)
When I see the Symfony profiler, I can see the values of the form in the "Request POST Parameters" section, but I'cant catch it and show it in the twig template...
that is the code wath dont work for my
$this->get('request')->request->get('campo', 'can not show it ¬¬')
in the template dont show the "campo" value, just "can not show it ¬¬"
this is my classType
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('Pais', 'entity', array(
'class' => 'UnadeniZonaBundle:Pais',
'property' => 'paisnomb',
))
->add('Provincia', 'entity', array(
'class' => 'UnadeniZonaBundle:Provincia',
'property' => 'provnomb',
))
->add('Ciudad', 'entity', array(
'class' => 'UnadeniZonaBundle:Ciudad',
'property' => 'ciudnomb',
))
->add('Campo', 'text', array(
'label' => 'campo',));
}
public function getName() {
return 'ciudad2';
}
}
My controller...
public function newAction(Request $request) {
$form = $this->createForm(new Ciudad2Type());
return $this->render('UnadeniZonaBundle:Ciudad2:new.html.twig', array(
'form' => $form->createView(),
'mensaje' => 'test'
));
}
public function showAction(Request $request) {
if ($request->isMethod('POST')) {
return $this->render('UnadeniZonaBundle:Ciudad2:show2.html.twig', array(
'mensaje' => $this->get('request')->request->get('campo', 'can not show it ¬¬')
));
}
}
this the templates
(new.html.twig)
{% extends '::base.html.twig' %}
{% block content -%}
<form action="{{ path('ciudad2_show') }}" method="post" {{ form_enctype(form) }}>
{{ form_widget(form) }}
<input type="submit" />
{{ mensaje }}
</form>
{% endblock %}
(Show2.html.twig)
{% extends '::base.html.twig' %}
{% block content -%}
{{ mensaje }}
{% endblock %}
If you try this :
$postData = $request->request->get('ciudad2');
$targetValue = $postData['Campo'];
return $this->render('UnadeniZonaBundle:Ciudad2:show2.html.twig', array(
'mensaje' => $targetValue)
));
It's a typo issue. Change campo to Campo in your controller.
if ($this->getRequest()->isMethod('POST')) {
$request = $this->getRequest->request;
$campo = $request->get('Campo', 'cannot show it.', true);
return $this->render('UnadeniZonaBundle:Ciudad2:show2.html.twig', array(
'mensaje' => $campo
));
}

Form default values is not shown

The problem as it is. I'm trying to set defalut form values, and there's no way i can achieve this.
Page layout
{% extends bundle ~ "Bundle::reg.html.twig" %}
{% form_theme regForm 'AcmeBundle:Form:order_type_fields.html.twig' %}
{% block content %}
<form action="{{ path('reg') }}" {{ form_enctype(regForm) }} method="POST">
<div>
{{ form_widget( regForm.firstname )}}
</div>
{{ form_rest( regForm )}}
<input type="submit>
</form>
{% endblock %}
fields layout
{% block text_widget %}
{% spaceless %}
<label>{{label}}</label>
<input type="text" {{ block('widget_attributes') }} value="{{ value }}">
{% endspaceless %}
{% endblock text_widget %}
Controller
$user = new User();
$regForm = $this->get('form.factory')->create(new RegForm(), $user);
return $this->render("FrontendBundle:Order:type.html.twig", array(
'regForm' => $regForm->createView(),
);
Form
class RegForm extends AbstractType
{
public function buildForm( FormBuilder $builder, array $options ){
$builder->add( 'firstname', 'text', array( 'label' => ' ', 'data' => 'Enter your name here' ) );
}
public function getName()
{
return 'reg';
}
}
I've already tried to set default field data in many ways:
in my controller by defining firstname field (
$user->setFirstname('Enter your name here');
).
In form builder by using setData method (
$builder->add( 'firstname', 'text', array( 'label' => ' ' ) )->setData(array('firstname' => 'Enter your name here'));
Or just
$builder->setData(array('firstname' => 'Enter your name here'));
All other form stuff work's just fine. For example, i can set label 'FIRSTNAME' without any problems. So, what am i missing?
UPD: After first answer i decided to ask a direct question:
Why doesn't work default value for this, while label works just fine:
$builder->add('firstname', 'text', array('label' => 'name', 'data' => 'Andrew'));
?
Maybe some mistakes in twig templates?
Have you tried this in your Form Type:
$builder
->add('firstname','hidden', array(
'attr' => array(
'value' => 'Enter your name here',
),
))
It seems to me, though, that you want to use a placeholder (HTML5) instead:
$builder
->add('firstname','hidden', array(
'attr' => array(
'placeholder' => 'Enter your name here',
),
))
In your controller, set the data on the $user object before creating the form
$user = new User();
$user->setFirstname('Default name');
$regForm = $this->get('form.factory')->create(new RegForm(), $user);
BTW you might want to use the placeholder attribute on the input:
<input placeholder="Enter your name here">
You can do this by adding the 'attr' option on the form builder:
$builder->add('firstname', 'text', array(
'attr' => array('placeholder' => 'Enter your name here'),
));