How to check whether field exists in symfony2 form? - php

Using this manual, I added dynamic field to my form. Now, how can I check existence of this field in my template?
{{ form_start(form) }}
{{ form_errors(form) }}
{% if ??? %} <---------------------------
{{ form_row(form.myDynamicField) }}
{% endif %}
{{ form_end(form) }}

What about,
{% if form.myDynamicField is defined %}
{{ form_row(form.myDynamicField) }}
{% endif %}
You may also need to check if form.myDynamicField is not null.

I know this question is a few years old, but you could also make it a shorter ternary operator.
{{ form.myDynamicField is defined ? form_row(form.myDynamicField) : null }}

{{ form_start(form) }}
{{ form_errors(form) }}
{% if form.getChildren['myDynamicField'] is defined %}
{{ form_row(form.myDynamicField) }}
{% endif %}
{{ form_end(form) }}

Related

Form errors not appear in a custom form theme with EasyAdmin3

I overrided my form in EasyAdmin to organize differently my input so I did like this :
In my Crud :
public function configureCrud(Crud $crud): Crud
{
return $crud
->setPageTitle(Crud::PAGE_INDEX, 'admin.menu.infos')
->setFormThemes(['bundles/EasyAdminBundle/crud/company/edit.html.twig'])
;
}
And in my Twig :
{% extends '#EasyAdmin/crud/form_theme.html.twig' %}
{% use '#EasyAdmin/symfony-form-themes/bootstrap_5_layout.html.twig' %}
{% block form %}
{{ form_start(form) }}
<div class="row">
{{ form_row(form.logo) }}
{{ form_row(form.phone) }}
{{ form_row(form.catchphrase) }}
</div>
<div class="row">
{{ form_row(form.businessName) }}
{{ form_row(form.email) }}
{{ form_row(form.website) }}
</div>
<div class="row">
{{ form_row(form.companyName) }}
{{ form_row(form.address) }}
{{ form_row(form.linkedin) }}
</div>
<div class="row">
{{ form_row(form.siren) }}
{{ form_row(form.zipcode) }}
{{ form_row(form.facebook) }}
</div>
<div class="row">
{{ form_row(form.legalForm) }}
{{ form_row(form.city) }}
{{ form_row(form.twitter) }}
</div>
<div class="row">
{{ form_row(form.description) }}
</div>
{{ form_end(form) }}
{% endblock %}
The form is like I wanted and when I submit, it's work but the problem is when I make an error. For example if I valid with an empty value, then instead of getting my form_errors, I've got a 500.
I've tried different things but none of them worked :
block errors :
{{ form_start(form) }}
{% block form_errors %}
{{ parent() }}
{% endblock %}
individual error :
{{ form_errors(form.businessName) }}
Any idea ?

symfony change attribut 'for' form_label

I search in google but i don't find how to change( surcharging) the 'for' attribut in a form_label.
{{ form_widget(form.star,{'id':'rating-input-1-5','attr':{'class':'rating-input'}}) }}
{{ form_label(form.star,null,{'label_attr':{'class':'rating-star','for':'rating-input-1-5'}}) }}
{{ form_widget(form.star,{'id':'rating-input-1-4','attr':{'class':'rating-input'}}) }}
{{ form_label(form.star,null,{'label_attr':{'class':'rating-star','for':'rating-input-1-4'}}) }}
{{ form_widget(form.star,{'id':'rating-input-1-3','attr':{'class':'rating-input'}}) }}
{{ form_label(form.star,null,{'label_attr':{'class':'rating-star','for':'rating-input-1-3'}}) }}
{{ form_widget(form.star,{'id':'rating-input-1-2','attr':{'class':'rating-input'}}) }}
{{ form_label(form.star,null,{'label_attr':{'class':'rating-star','for':'rating-input-1-2'}}) }}
{{ form_widget(form.star,{'id':'rating-input-1-1','attr':{'class':'rating-input'}}) }}
{{ form_label(form.star,null,{'label_attr':{'class':'rating-star','for':'rating-input-1-1'}}) }}
I want that the form_label point on the id of my form_widget.
Is it possible ?
Thanks for your answer
Try to change form_label call to
{{ form_label(form.star,null,{'id':'rating-input-1-5', 'label_attr':{'class':'rating-star'}}) }}

Partial User Registration on Home Page (index)

I am using Symfony2 2.6.4 with the FOS User Bundle (master) and I am having a hard time trying to pass a partial registration from the home page to the registration page.
The Goal
I want a user to start on the home page and fill out some info and press submit. I want the user to be passed to the registration page and pre fill the items that they have already filled out on the front page.
Things I have tried:
I am unsure what is feasable and have already spend too much time on this. I tried extending the registration controller but I am getting errors before I can even start on my issue so I stopped. My last thought was to pass the variables in a session to the overridden registration form type and see if I can pre-populate it there.
Has anyone done anything like this before? They sure don't make it easy.
Credit goes to #NawfalSerrar Thank you for the idea. I was close but not close enough!
So what I ended up doing was this.
This is the controller action that does that work.
/**
* #Route("/", name="Home")
*/
public function indexAction(Request $request)
{
$form = $this->createForm(new RegisterFormType());
$form->handleRequest($request);
if ($form->isValid()) {
$data = $form->getData();
$user = new User();
$session = $this->get('session');
$registration = array();
$registration['firstName'] = $data['first'];
$registration['lastName'] = $data['last'];
$registration['middleInit'] = $data['middle'];
$registration['email'] = $data['email'];
$session->set('registration', $registration);
return $this->redirect($this->generateUrl("fos_user_registration_register"));
}
return $this->render('Bundle:Page:index.html.twig', array(
'form' => $form->createView(),
));
}
Then the form on the front end.
{{ form_start(form,{'attr': {'class': 'reg-page'}}) }}
<div class="reg-header">
<h1>Get Started!</h1>
<p>Already Signed Up? Click Sign In to login
your account.</p>
</div>
{{ form_errors(form) }}
<div class="row">
<div class="col-sm-6">
{{ form_label(form.first) }}
{{ form_widget(form.first, {'attr': {'class': 'form-control margin-bottom-10'}}) }}
</div>
<div class="col-sm-6">
{{ form_label(form.middle) }}
{{ form_widget(form.middle, {'attr': {'class': 'form-control margin-bottom-10'}}) }}
</div>
<div class="col-sm-6">
{{ form_label(form.last) }}
{{ form_widget(form.last, {'attr': {'class': 'form-control margin-bottom-10'}}) }}
</div>
</div>
{{ form_label(form.email) }}
{{ form_widget(form.email, {'attr': {'class': 'form-control'}}) }}
<div class="row">
<div class="col-lg-6 text-right">
{{ form_widget(form.save, {'attr': {'class': 'btn-u'}}) }}
</div>
</div>
{{ form_end(form) }}
Registration page looks like this.
{% extends '::base.html.twig' %}
{% block body %}
{% set tokens = app.session.get('registration') %}
{% if tokens['firstName'] is defined %}
{% set firstName = tokens['firstName'] %}
{% endif %}
{% if tokens['middleInit'] is defined %}
{% set middleInit = tokens['middleInit'] %}
{% endif %}
{% if tokens['lastName'] is defined %}
{% set lastName = tokens['lastName'] %}
{% endif %}
{% if tokens['email'] is defined %}
{% set email = tokens['email'] %}
{% endif %}
{{ form_start(form) }}
{{ form_errors(form) }}
{{ form_label(form.firstName, 'First Name', {label_attr: {class: 'foo'}}) }}
{% if firstName is defined %}
{{ form_widget(form.firstName, { attr: {class: 'TestClass'}, value : firstName }) }}
{% else %}
{{ form_widget(form.firstName, { attr: {class: 'TestClass'} }) }}
{% endif %}
{{ form_label(form.middleInitial) }}
{% if middleInitial is defined %}
{{ form_widget(form.middleInitial, { attr: {class: 'TestClass'}, value : middleInit }) }}
{% else %}
{{ form_widget(form.middleInitial, { attr: {class: 'TestClass'}}) }}
{% endif %}
{{ form_label(form.lastName) }}
{% if lastName is defined %}
{{ form_widget(form.lastName, { attr: {class: 'TestClass'}, value : lastName }) }}
{% else %}
{{ form_widget(form.lastName, { attr: {class: 'TestClass'}}) }}
{% endif %}
{{ form_label(form.email) }}
{% if email is defined %}
{{ form_widget(form.email, { attr: {class: 'TestClass'}, value : email }) }}
{% else %}
{{ form_widget(form.email, { attr: {class: 'TestClass'}}) }}
{% endif %}
{{ form_label(form.plainPassword.first) }}
{{ form_widget(form.plainPassword.first) }}
{{ form_label(form.plainPassword.second) }}
{{ form_widget(form.plainPassword.second) }}
<div>
<input type="submit" value="{{ 'registration.submit'|trans }}"/>
</div>
{{ form_end(form) }}
{% endblock %}
Hope this helps!

Symfony2: how to render form submit separately

I'm creating a form in Symfony2 that contains more than one submit button. I need to control where these buttons are rendered. I tried the following, but naturally nothing happens.
<h1>Search Form</h1>
<div id="search_form">
{{ form(formSearch) }}
</div>
<div id="search_tasks">
Tasks:
{{ form_widget(formSearch.searchButton1) }}
{{ form_widget(formSearch.searchButton2) }}
</div>
The search buttons are declared in the form class; they are rendered inside #search_form and nothing shows up in #search_tasks.
You are already rendering the whole form with {{ form(formSearch) }} (fields and buttons are only rendered once).
You need to render the start, rows and end separately.
{{ form_start(formSearch) }}
<h1>Search Form</h1>
<div id="search_form">
{{ form_row(formSearch.field1) }}
{{ form_row(formSearch.field2) }}
{{ form_row(formSearch.field3) }}
</div>
<div id="search_tasks">
Tasks:
{{ form_widget(formSearch.searchButton1) }}
{{ form_widget(formSearch.searchButton2) }}
</div>
{{ form_end(formSearch) }}
I ran into the same issue where I needed my Submit and Reset buttons to be on the same row. My forms are dynamic so there was no way I could output the fields individually. I captured the buttons' HTML first so that form_widget(form) wouldn't output them for me.
{% form_theme form 'AppBundle::form/form_layout.html.twig' %}
<div class="row">
{{ form_start(form) }}
{% if form.submit is defined %}
{% set submitButton = form_widget(form.submit) %}
{% endif %}
{% if form.reset is defined %}
{% set resetButton = form_widget(form.reset) %}
{% endif %}
{{ form_widget(form) }}
<div class="form-group row">
{% if submitButton is defined %}
{{ submitButton|raw }}
{% endif %}
{% if resetButton is defined %}
{{ resetButton|raw }}
{% endif %}
</div>
{{ form_end(form) }}
</div>

Symfony2 Form Builder - Remove label, make it placeholder

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'];
}
}

Categories