10

I have the following Symfony form field, it's a drop down that loads from an entity:

->add('measureunit', 'entity', array('label' => 'Measure Unit',
            'class' => 'TeamERPBaseBundle:MeasureUnit',
            'expanded' => false, 'empty_value' => '',
            'multiple' => false, 'property' => 'abreviation'
        ))

As you can see I have added 'empty_value' => '' and everything works fine. Now, what I want is to have an extra option at the end to add a let say new measure unit. In other words the dropdown should display all the content of my entity, the empty value and other extra option called new measure unit or what ever I want to call it. Is it possible?

Edit: The whole form type file has this:

<?php
namespace TeamERP\StoresBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class ProductType  extends AbstractType 
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
        ->add('name', 'text', array('label'=>'Product name', 'required' => true,
        'attr' => array('class' => 'form-control')))
        ->add('code', 'text', array('label'=>'Code', 'required' => false,
        'attr' => array('class' => 'form-control')))
        ->add('description', 'text', array('label'=>'Description', 'required' => false,
        'attr' => array('class' => 'form-control')))
        ->add('cost', 'money', array('label'=>'Cost', 'divisor' => 100, 'currency' => 'BWP'))
        ->add('category', new CategoryType(), array('required' => false))
        ->add('measureunit', 'entity', array('label' => 'Measure Unit',
            'class' => 'TeamERPBaseBundle:MeasureUnit',
            'expanded' => false, 'placeholder' => '',
            'multiple' => false, 'property' => 'abreviation'
        ))
        ->add('qtyToPurchase', 'number', array('label'=>'Quantity to purchase', 'required' => false,
        'attr' => array('class' => 'form-control')))
        ->add('reorderPoint', 'number', array('label'=>'Reorder point', 'required' => false,
        'attr' => array('class' => 'form-control')))
        ->add('qtyOnSalesOrder', 'number', array('label'=>'Quantity on sales order', 'required' => false,
        'attr' => array('class' => 'form-control')));
    }
public function getName()
    {
        return 'product';
    }
public function finishView(FormView $view, FormInterface $form, array $options)
    {
        $new_choice = new ChoiceView(array(), 'add', 'add new'); // <- new option
        $view->children['measureunit']->vars['choices'][] = $new_choice;//<- adding the new option 
    }
}

Error: Compile Error: Declaration of TeamERP\StoresBundle\Form\Type\ProductType::finishView() must be compatible with Symfony\Component\Form\FormTypeInterface::finishView(Symfony\Component\Form\FormView $view, Symfony\Component\Form\FormInterface $form, array $options)

Edit2 Working form file:

<?php
namespace TeamERP\StoresBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormView; 
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\Extension\Core\View\ChoiceView;
class ProductType  extends AbstractType 
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
        ->add('name', 'text', array('label'=>'Product name', 'required' => true,
        'attr' => array('class' => 'form-control')))
        ->add('code', 'text', array('label'=>'Code', 'required' => false,
        'attr' => array('class' => 'form-control')))
        ->add('description', 'text', array('label'=>'Description', 'required' => false,
        'attr' => array('class' => 'form-control')))
        ->add('cost', 'money', array('label'=>'Cost', 'divisor' => 100, 'currency' => 'BWP'))
        ->add('category', new CategoryType(), array('required' => false))
        ->add('measureunit', 'entity', array('label' => 'Measure Unit',
            'class' => 'TeamERPBaseBundle:MeasureUnit',
            'expanded' => false, 'placeholder' => '',
            'multiple' => false, 'property' => 'abreviation'
        ))
        ->add('qtyToPurchase', 'number', array('label'=>'Quantity to purchase', 'required' => false,
        'attr' => array('class' => 'form-control')))
        ->add('reorderPoint', 'number', array('label'=>'Reorder point', 'required' => false,
        'attr' => array('class' => 'form-control')))
        ->add('qtyOnSalesOrder', 'number', array('label'=>'Quantity on sales order', 'required' => false,
        'attr' => array('class' => 'form-control')));
    }
public function getName()
    {
        return 'product';
    }
public function finishView(FormView $view, FormInterface $form, array $options)
    {
        $new_choice = new ChoiceView(array(), 'add', 'add new'); // <- new option
        $view->children['measureunit']->vars['choices'][] = $new_choice;//<- adding the new option 
    }
}

2 Answers 2

23

In your form type override the function finishView:

public function buildForm(FormbuilderInterface $builder, array $options){
    $builder->add('measureunit', EntityType::class, array(
        'label' => 'Measure Unit',
        'class' => 'TeamERPBaseBundle:MeasureUnit',
        'expanded' => false, 
        'empty_value' => '',
        'multiple' => false, 
        'property' => 'abbreviation'
    ));
}

public function finishView(FormView $view, FormInterface $form, array $options)
{
    $newChoice = new ChoiceView(array(), 'add', 'Add New'); // <- new option
    $view->children['measureunit']->vars['choices'][] = $newChoice;//<- adding the new option 
}

You will get a new option 'add new' with value 'add' to the bottom of the field.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks, I get this error: Compile Error: Declaration of TeamERP\StoresBundle\Form\Type\ProductType::finishView() must be compatible with Symfony\Component\Form\FormTypeInterface::finishView(Symfony\Component\Form\FormView $view, Symfony\Component\Form\FormInterface $form, array $options)
I think your are missing to import the FormView and FormInterface components , try adding those two lines to the use list use Symfony\Component\Form\FormView; use Symfony\Component\Form\FormInterface;
Thank you it worked, I just had to add this as well: use Symfony\Component\Form\Extension\Core\View\ChoiceView;
Of note: as this value is not part of the initial list (will produce a validation error), you'll need to either (1) "deal" with it on JS so the server never sees it, or (2) use a data transformer to "deal" with.
@DarrylHein The easiest way is to deal with listener.
3

In addition to accepted answer:

If you choose the added option you will get validation error (because it's not valid entity), the following snippet can be used to overcome this error:

$builder->addEventListener(
        FormEvents::PRE_SUBMIT,
        function (FormEvent $event) {
            if ($event->getData() === 'add') {
                $event->setData(null);
            }
        }
    );

Then you can check if selected option is NULL, if it's => take value from additional input field.

2 Comments

Can you explain this comment further? "Then you can check if selected option is NULL, if it's => take value from additional input field." Thanks!
What I mean is => If you select that additional option you will receive validation error from Symfony itself -> that's why if selected value is 'add' - we replace it by NULL - so symfony will not throw validation error. Then you can check - If value of field is NULL -> then do your logic.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.