Validating dynamically loaded choices in Symfony 2

后端 未结 5 1318
独厮守ぢ
独厮守ぢ 2020-12-08 16:08

I have a choice field type named *sub_choice* in my form whose choices will be dynamically loaded through AJAX depending on the selected value of the parent choice field, na

相关标签:
5条回答
  • 2020-12-08 16:21

    To do the trick you need to overwrite the sub_choice field before submitting the form:

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        ...
    
        $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
            $parentChoice = $event->getData();
            $subChoices = $this->getValidChoicesFor($parentChoice);
    
            $event->getForm()->add('sub_choice', 'choice', [
                'label'   => 'Sub Choice',
                'choices' => $subChoices,
            ]);
        });
    }
    
    0 讨论(0)
  • 2020-12-08 16:23

    Suppose for sub choices you have id's right ? Create and empty array with a certain number of values and give it as a choice

    $indexedArray = []; for ($i=0; $i<999; $i++){ $indexedArray[$i]= ''; }

    then 'choices' => $indexedArray, :)

    0 讨论(0)
  • 2020-12-08 16:27

    Adding an alternate approach for future readers since I had to do a lot of investigation to get my form working. Here is the breakdown:

    1. Adding a "New" option to a dropdown via jquery
    2. If "New" is selected display new form field "Custom Option"
    3. Submit Form
    4. Validate data
    5. Save to database

    jquery code for twig:

    $(function(){
        $(document).ready(function() {
            $("[name*='[custom_option]']").parent().parent().hide(); // hide on load
    
            $("[name*='[options]']").append('<option value="new">New</option>'); // add "New" option
            $("[name*='[options]']").trigger("chosen:updated");
        });
    
        $("[name*='[options]']").change(function() {
            var companyGroup = $("[name*='[options]']").val();
    
            if (companyGroup == 'new') { // when new option is selected display text box to enter custom option
                $("[name*='[custom_option]']").parent().parent().show();
            } else {
                $("[name*='[custom_option]']").parent().parent().hide();
            }
        });
    });
    
    // Here's my Symfony 2.6 form code:
        ->add('options', 'entity', [
        'class'         => 'Acme\TestBundle\Entity\Options',
        'property'      => 'display',
        'empty_value'   => 'Select an Option',
        'mapped'        => true,
        'property_path' => 'options.optionGroup',
        'required' => true,
    ])
    ->add('custom_option', 'text', [
        'required' => false,
        'mapped'   => false,
    ])
    

    To handle the form data we need to use the PRE_SUBMIT form event.

        $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
        $data = $event->getData();
        $form = $event->getForm();
        if (isset($data['options']) && $data['options'] === 'new') {
            $customOption = $data['custom_option'];
    
            // todo: handle this better on your own
            if (empty($customOption)) {
                $form->addError(new FormError('Please provide a custom option'));
                return;
            }
    
            // Check for a duplicate option
            $matches = $this->doctrine->getRepository('Acme\TestBundle\Entity\Options')->matchByName([$customOption]);
            if (count($matches) > 0) {
                $form->addError(new FormError('Duplicate option found'));
                return;
            }
    
            // More validation can be added here
    
            // Creates new option in DB
            $newOption = $this->optionsService->createOption($customOption); // return object after persist and flush in service
            $data['options'] = $newOption->getOptionId();
            $event->setData($data);
        }
    });
    

    Let me know if ya'll have any questions or concerns. I know this might not be the best solution but it works. Thanks!

    0 讨论(0)
  • 2020-12-08 16:31

    you cannot not build the sub_choice validation because during you config its validator you don't know which values are valid (values depend on value of parent_choice).

    What you can do is to resolve parent_choice into entity before you make new YourFormType() in your controller. Then you can get all the possible values for sub_choice and provide them over the form constructor - new YourFormType($subChoice).

    In YourFormType you have to add __construct method like this one:

    /**
     * @var array
     */
    protected $subChoice = array();
    
    public function __construct(array $subChoice)
    {
        $this->subChoice = $subChoice;
    }
    

    and use provided values in form add:

    $builder->add('sub_choice', 'choice', array(
                    'label' => 'Sub Choice',
                    'choices' => $this->subChoice,
                    'virtual' => true
    ));
    
    0 讨论(0)
  • 2020-12-08 16:36

    this accept any value

     $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
        $data = $event->getData();
        if(is_array($data['tags']))$data=array_flip($data['tags']);
        else $data = array();
        $event->getForm()->add('tags', 'tag', [
            'label'   => 'Sub Choice',
            'choices' => $data,
            'mapped'=>false,
            'required'=>false,
            'multiple'=>true,
        ]);
    });
    
    0 讨论(0)
提交回复
热议问题