symfony validation symfony-2.1

Validar opciones cargadas dinĂ¡micamente en Symfony 2



validation symfony-2.1 (5)

Tengo un tipo de campo de elección llamado * sub_choice * en mi formulario cuyas elecciones se cargarán dinámicamente a través de AJAX dependiendo del valor seleccionado del campo de elección principal, llamado * parent_choice *. La carga de las opciones funciona a la perfección, pero tengo un problema al validar el valor de sub_choice al enviarlo. Da un error de validación "Este valor no es válido" ya que el valor enviado no está en las opciones del campo sub_choice cuando se construyó. Entonces, ¿hay alguna manera de validar correctamente el valor enviado del campo sub_choice? Abajo está el código para construir mi formulario. Estoy usando Symfony 2.1.

public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add(''parent_choice'', ''entity'', array( ''label'' => ''Parent Choice'', ''class'' => ''Acme/TestBundle/Entity/ParentChoice'' )); $builder->add(''sub_choice'', ''choice'', array( ''label'' => ''Sub Choice'', ''choices'' => array(), ''virtual'' => true )); }


Agregando un enfoque alternativo para futuros lectores ya que tuve que hacer mucha investigación para que mi formulario funcionara. Aquí está el desglose:

  1. Agregar una opción "Nueva" a un menú desplegable a través de jQuery
  2. Si se selecciona "Nuevo", se mostrará el nuevo campo de formulario "Opción personalizada"
  3. Enviar formulario
  4. Validar datos
  5. Guardar en la base de datos

código jquery para ramita:

$(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, ])

Para manejar los datos del formulario necesitamos usar el evento de formulario PRE_SUBMIT.

$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); } });

Avísame si tienes alguna pregunta o inquietud. Sé que esta podría no ser la mejor solución pero funciona. ¡Gracias!


Para hacer el truco, debe sobrescribir el campo sub_choice antes de enviar el formulario:

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, ]); }); }


Supongamos que para las elecciones secundarias tienes el derecho de identificación? Crea y vacía una matriz con un cierto número de valores y dale como opción

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

entonces ''choices'' => $indexedArray, :)


esto acepta cualquier valor

$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, ]); });


no puede no crear la validación de sub_choice porque durante su configuración de su validador no sabe qué valores son válidos (los valores dependen del valor de parent_choice).

Lo que puede hacer es resolver parent_choice en entidad antes de crear un nuevo YourFormType () en su controlador. Luego, puede obtener todos los valores posibles para sub_choice y proporcionarlos a través del constructor de formularios: nuevo YourFormType ($ subChoice).

En YourFormType tienes que agregar el método __construct como este:

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

y usar los valores proporcionados en forma agregar:

$builder->add(''sub_choice'', ''choice'', array( ''label'' => ''Sub Choice'', ''choices'' => $this->subChoice, ''virtual'' => true ));