By default, {{ form() }}
and {{ form_row() }}
are kind of aliases for {{ form_label() }}
,
{{ form_widget() }}
and {{ form_errors() }}
. If you want to avoid displaying useless labels for your
collection elements, you should not use {{ form_row() }}
, but manually render {{ form_widget() }}
and
{{ form_errors() }}
instead.
Should Eat before March 22, 2016 00:00
Should Sleep before March 23, 2016 00:00
Should Eat before March 22, 2016 00:00
Should Sleep before March 23, 2016 00:00
Should Eat before March 22, 2016 00:00
Should Sleep before March 23, 2016 00:00
<?php
namespace Fuz\AppBundle\Controller;
use Fuz\AppBundle\Base\BaseController;
use Fuz\AppBundle\Entity\Task;
use Fuz\AppBundle\Entity\Tasks;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\Form\Extension\Core\Type;
use Symfony\Component\HttpFoundation\Request;
/**
* @Route("/troubleshoot")
*/
class TroubleshootController extends BaseController
{
/**
* Basic usage
*
* @Route("/hide-form-labels", name="hideFormLabels")
* @Template()
*/
public function hideFormLabelsAction(Request $request)
{
$dataA = new Tasks();
$dataB = new Tasks();
$dataC = new Tasks();
$task = new Task();
$task->setTask('Eat');
$task->setDueDate(new \DateTime('2016-03-22'));
$dataA->getTasks()->add($task);
$dataB->getTasks()->add($task);
$dataC->getTasks()->add($task);
$task = new Task();
$task->setTask('Sleep');
$task->setDueDate(new \DateTime('2016-03-23'));
$dataA->getTasks()->add($task);
$dataB->getTasks()->add($task);
$dataC->getTasks()->add($task);
$formA = $this->get('form.factory')->createNamed('havingLabels', 'Fuz\AppBundle\Form\TasksType', $dataA);
$formB = $this->get('form.factory')->createNamed('withoutLabels', 'Fuz\AppBundle\Form\TasksType', $dataB);
$formC = $this->get('form.factory')->createNamed('withFormTheme', 'Fuz\AppBundle\Form\TasksType', $dataB);
if ($request->isMethod('POST')) {
$formA->handleRequest($request);
$formB->handleRequest($request);
$formC->handleRequest($request);
}
return [
'formA' => $formA->createView(),
'dataA' => $dataA,
'formB' => $formB->createView(),
'dataB' => $dataB,
'formC' => $formC->createView(),
'dataC' => $dataC,
];
}
/**
* A form having a theme and containing several fields
*
* @Route(
* "/custom-jquery-version",
* name = "customJqueryVersion"
* )
* @Template()
*/
public function customJqueryVersionAction(Request $request)
{
$data = ['values' => ['a', 'b', 'c']];
$form = $this
->get('form.factory')
->createNamedBuilder('form', Type\FormType::class, $data)
->add('url', Type\TextType::class)
->add('values', Type\CollectionType::class, [
'entry_type' => Type\TextType::class,
'entry_options' => [
'label' => 'Value',
],
'label' => 'Add, move, remove values and press Submit.',
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
'attr' => [
'class' => 'form-collection',
],
])
->add('submit', Type\SubmitType::class)
->getForm()
;
$jquery = '';
$form->handleRequest($request);
if ($form->isValid()) {
$data = $form->getData();
$jquery = $form->getData()['url'];
}
return [
'jquery' => $jquery,
'form' => $form->createView(),
'data' => $data,
];
}
}
<?php
namespace Fuz\AppBundle\Entity;
class Task
{
protected $task;
protected $dueDate;
public function getTask()
{
return $this->task;
}
public function setTask($task)
{
$this->task = $task;
}
public function getDueDate()
{
return $this->dueDate;
}
public function setDueDate(\DateTime $dueDate = null)
{
$this->dueDate = $dueDate;
}
}
<?php
namespace Fuz\AppBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
class Tasks
{
protected $tasks;
public function __construct()
{
$this->tasks = new ArrayCollection();
}
public function getTasks()
{
return $this->tasks;
}
}
<?php
namespace Fuz\AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class TaskType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
// want to know your form type name? try this:
// die($this->getBlockPrefix());
$builder
->add('task', 'Symfony\Component\Form\Extension\Core\Type\TextType')
->add('dueDate', 'Symfony\Component\Form\Extension\Core\Type\DateType')
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => 'Fuz\AppBundle\Entity\Task',
]);
}
}
<?php
namespace Fuz\AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class TasksType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('tasks', CollectionType::class, [
'label' => 'Tasks',
'entry_type' => TaskType::class,
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
'required' => false,
'by_reference' => true,
'delete_empty' => true,
]);
$builder->add('save', SubmitType::class, [
'label' => 'See my tasks',
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => 'Fuz\AppBundle\Entity\Tasks',
]);
}
}
{% extends 'FuzAppBundle::layout.html.twig' %}
{% block extra_js %}
<script src="{{ asset('js/jquery.collection.js') }}"></script>
{% endblock %}
{% block title %}Hide form labels{% endblock %}
{% block body %}
<h2>{{ block('title') }}</h2>
{% verbatim %}
<p>
By default, <code>{{ form() }}</code> and <code>{{ form_row() }}</code> are kind of aliases for <code>{{ form_label() }}</code>,
<code>{{ form_widget() }}</code> and <code>{{ form_errors() }}</code>. If you want to avoid displaying useless labels for your
collection elements, you should not use <code>{{ form_row() }}</code>, but manually render <code>{{ form_widget() }}</code> and
<code>{{ form_errors() }}</code> instead.
</p>
{% endverbatim %}
<div class="row">
<div class="col-md-4">
{# Demo A : default behavior #}
{% form_theme formA 'jquery.collection.html.twig' %}
<h3>By default, {% verbatim %}{{ form_row() }}{% endverbatim %}</h3>
{{ form_start(formA) }}
{{ form_row(formA.tasks, {'attr': {'class': 'collectionA'} }) }}
{{ form_end(formA) }}
{% for task in dataA.tasks %}
<p>Should <strong>{{ task.task }}</strong> before <strong>{{ task.dueDate|date }}</strong></p>
{% endfor %}
</div>
<div class="col-md-4">
{# Demo B : hiding labels without using form theme #}
<h3>By using {% verbatim %}{{ form_widget() }} {% endverbatim %} without form theme</h3>
{{ form_start(formB) }}
<div
id="formB-demo"
class="collectionB"
{% if formB.tasks.vars.prototype is defined %}
data-prototype="{{ form_widget(formB.tasks.vars.prototype)|e('html_attr') }}"
data-prototype-name="{{ formB.tasks.vars.prototype.vars.name|e('html_attr') }}"
{% endif %}
data-allow-add="{{ formB.tasks.vars.allow_add }}"
data-allow-remove="{{ formB.tasks.vars.allow_delete }}"
data-name-prefix="{{ formB.tasks.vars.full_name }}"
>
{% for task in formB.tasks %}
{{ form_widget(task) }}
{{ form_errors(task) }}
{% endfor %}
</div>
{{ form_end(formB) }}
{% for task in dataB.tasks %}
<p>Should <strong>{{ task.task }}</strong> before <strong>{{ task.dueDate|date }}</strong></p>
{% endfor %}
</div>
<div class="col-md-4">
{# Demo C : using a form theme #}
<h3>By using a form theme [Recommanded]</h3>
{# "task" is your field type name (look at the comments in TaskType) #}
{% block task_label %}{% endblock %}
{# "_self" will use the block declared above to overwrite the default theme #}
{% form_theme formC _self 'jquery.collection.html.twig' %}
{{ form_start(formC) }}
{{ form_row(formC.tasks, {'attr': {'class': 'collectionA'} }) }}
{{ form_end(formC) }}
{% for task in dataC.tasks %}
<p>Should <strong>{{ task.task }}</strong> before <strong>{{ task.dueDate|date }}</strong></p>
{% endfor %}
</div>
</div>
<hr/>
{{
tabs([
'Controller/TroubleshootController.php',
'Entity/Task.php',
'Form/TaskType.php',
'Entity/Tasks.php',
'Form/TasksType.php',
'Resources/views/Troubleshoot/hideFormLabels.html.twig',
])
}}
{% endblock %}
{% block script %}
<script type="text/javascript">
$('.collectionA').collection();
$('.collectionB').collection();
$('.collectionC').collection();
</script>
{% endblock %}