Disable An Option From An EntityFormType,
today a coworker of mine tryed to disable one option field based on an attribute for the entity form type. the entity form type provides a great solution for displaying a selectboxes (with optgroups) or multiselects based on a doctrine entity.
<?php
/**
* @Template("TgDemoFormBundle:Demo/Form:base.html.twig")
* @Route("/demo/form/data")
*/
function dataAction() {
$builder = $this->formFactory->createBuilder()
->add('foo', 'entity', array(
'class' => ChoiceDemo::CLASS,
'data' => 'TgDemoFromBundle:ChoiceDemo'
))
;
return array(
'form' => $builder->getForm()->createView()
);
}
at least you’ve to define the entity (data) and the entity class (class). there a a lot of optional stuff you can provide, just read the awesome manual :).
the entity looks like this:
<?php
namespace Tg\Demo\FormBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Class ChoiceDemo
* @package Tg\Demo\FormBundle\Entity
* @ORM\Entity
*/
class ChoiceDemo {
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
public $id;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
public $fieldA;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
public $fieldB;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
public $fieldC;
/**
* @ORM\Column(type="boolean")
*/
public $isActive = false;
function __toString() {
return $this->fieldA;
}
}
go on and define some Fixtures (never skip this :)).
<?php
namespace Tg\Demo\FormBundle\DataFixtures;
use Doctrine\Common\DataFixtures\Doctrine;
use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Tg\Demo\FormBundle\Entity\ChoiceDemo;
class LoadDemoChoices implements FixtureInterface {
function load(ObjectManager $manager)
{
$choiceDemo = new ChoiceDemo();
$choiceDemo->fieldA = 'fieldA1';
$choiceDemo->fieldB = 'fieldB1';
$choiceDemo->fieldC = 'fieldC1';
$choiceDemo->isActive = true;
$manager->persist($choiceDemo);
$choiceDemo = new ChoiceDemo();
$choiceDemo->fieldA = 'fieldA2';
$choiceDemo->fieldB = 'fieldB2';
$choiceDemo->fieldC = 'fieldC2';
$choiceDemo->isActive = false;
$manager->persist($choiceDemo);
$choiceDemo = new ChoiceDemo();
$choiceDemo->fieldA = 'fieldA3';
$choiceDemo->fieldB = 'fieldB3';
$choiceDemo->fieldC = 'fieldC3';
$choiceDemo->isActive = true;
$manager->persist($choiceDemo);
$manager->flush();
}
}
the challenge is that we want to display a disabled=”disabled” attribute if the isActive flag is false. the solution is quite simple. just overwrite the correct part of your template.
{% extends '::base.html.twig' %}
{% form_theme form.foo _self %}
{% block choice_widget_options %}
{% spaceless %}
{% for group_label, choice in options %}
{% if choice is iterable %}
<optgroup label="{{ group_label|trans({}, translation_domain) }}">
{% set options = choice %}
{{ block('choice_widget_options') }}
</optgroup>
{% else %}
<option {% if choice.data.isActive == true %}" disabled="disabled" {% endif %} value="{{ choice.value }}"{% if choice is selectedchoice(value) %} selected="selected"{% endif %}>{{ choice.label|trans({}, translation_domain) }}</option>
{% endif %}
{% endfor %}
{% endspaceless %}
{% endblock %}
{% block body %}
{{ form(form) }}
{% endblock %}
look at the options tag. instead of using _this as form theme i would suggest to use a different file. i just overwrote the template for form element, so it’s possible to just overwrite this block.
you can add a list of form themes to the form_theme tag :)