Szukaj…
Jak rozszerzyć ChoiceType, EntityType i DocumentType, aby załadować opcje za pomocą AJAX.
W Symfony wbudowany ChoiceType (i EntityType lub DocumentType go rozszerzający) zasadniczo działa ze stałą listą wyboru.
Jeśli chcesz, aby działało z wywołaniami ajax, musisz je zmienić, aby akceptować wszelkie sumowane dodatkowe opcje.
Jak zacząć od pustej listy wyboru?
Podczas budowania formularza po prostu ustaw opcję
choices
na pustąarray()
:namespace AppBundle\Form; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; class FooType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('tag', ChoiceType::class, array('choices'=>array())); } }
Otrzymasz pusty wybór wejściowy, bez wyborów. To rozwiązanie działa dla ChoiceType i wszystkich jego dzieci (EntityType, DocumentType, ...).
Jak zaakceptować przesłane nowe opcje :
Aby zaakceptować nowe wybory, musisz je udostępnić w liście wyboru pola formularza. Możesz zmienić pole formularza w zależności od przesłanych danych za pomocą zdarzenia FormEvent :: PRE_SUBMIT.
Ten przykład pokazuje, jak to zrobić za pomocą podstawowego ChoiceType:
namespace AppBundle\Form; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; class FooType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('tag', ChoiceType::class, array('choices'=>array())) ; $builder->addEventListener( FormEvents::PRE_SUBMIT, function(FormEvent $event){ // Get the parent form $form = $event->getForm(); // Get the data for the choice field $data = $event->getData()['tag']; // Collect the new choices $choices = array(); if(is_array($data)){ foreach($data as $choice){ $choices[$choice] = $choice; } } else{ $choices[$data] = $data; } // Add the field again, with the new choices : $form->add('tag', ChoiceType::class, array('choices'=>$choices)); } ); } }
Twoje przesłane opcje są teraz dozwolone, a wbudowane sprawdzanie poprawności Symfony ChoiceType nie będzie już ich odrzucać.
Jeśli chcesz zrobić to samo z dzieckiem potomnym ChoiceType (EntityType, DocumentType, ...), musisz wstrzyknąć encję Managera lub managera dokumentu i wykonać transformację danych podczas zapełniania nowych opcji.
Wypełnij pole wyboru w zależności od innej wartości.
Jest to przykład pokazujący, jak zmienić dozwolone wybory w polu wyboru podkategorii w zależności od wartości pola wyboru kategorii. Aby to zrobić, musisz dokonać dynamicznych wyborów podkategorii zarówno po stronie klienta, jak i serwera.
1. Uczyń formularz dynamicznym po stronie klienta w celu wyświetlania / interakcji użytkownika
Przykład dynamicznej formy po stronie klienta (przy użyciu Javascript / JQuery):
$('#category').change(function(){
switch($(this).val()){
case '1': // If category == '1'
var choice = {
'choice1_1':'1_1',
'choice1_2':'1_2',
'choice1_3':'1_3',
};
break;
case '2': // If category == '2'
var choice = {
'choice2_1':'2_1',
'choice2_2':'2_2',
'choice2_3':'2_3',
};
break;
case '3': // If category == '3'
var choice = {
'choice3_1':'3_1',
'choice3_2':'3_2',
'choice3_3':'3_3',
};
break;
}
var $subCategorySelect = $('#subCategory');
$subCategorySelect.empty();
$.each(choice, function(key, value) {
$subCategorySelect.append($('<option></option>')).attr('value',value).text(key);
});
});
Oczywiście możesz wybierać z połączenia AJAX. To nie jest celem tego przykładu.
2. Uczyń formularz dynamicznym po stronie serwera w celu inicjalizacji / weryfikacji
Przykład dynamicznej formy po stronie serwera:
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
class MyBaseFormType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('category',ChoiceType::class,array('choices'=>array(
'choice1'=>'1',
'choice2'=>'2',
'choice3'=>'3',
)))
;
$addSubCategoryListener = function(FormEvent $event){
$form = $event->getForm();
$data = $event->getData();
switch($data['category']){
case '1': // If category == '1'
$choices = array(
'choice1_1'=>'1_1',
'choice1_2'=>'1_2',
'choice1_3'=>'1_3',
);
break;
case '2': // If category == '2'
$choices = array(
'choice2_1'=>'2_1',
'choice2_2'=>'2_2',
'choice2_3'=>'2_3',
);
break;
case '3': // If category == '3'
$choices = array(
'choice3_1'=>'3_1',
'choice3_2'=>'3_2',
'choice3_3'=>'3_3',
);
break;
}
$form->add('subCategory',ChoiceType::class,array('choices'=>$choices));
};
// This listener will adapt the form with the data passed to the form during construction :
$builder->addEventListener(FormEvents::PRE_SET_DATA, $addSubCategoryListener);
// This listener will adapt the form with the submitted data :
$builder->addEventListener(FormEvents::PRE_SUBMIT, $addSubCategoryListener);
}
}