Zoeken…
Hoe ChoiceType, EntityType en DocumentType uit te breiden om keuzes te laden met AJAX.
In Symfony, het ingebouwde ChoiceType (en EntityType of DocumentType dat het uitbreidt), werkt in principe met een constante keuzelijst.
Als u ervoor wilt zorgen dat het werkt met Ajax-oproepen, moet u deze wijzigen om alle opgetelde extra keuzes te accepteren.
Hoe te beginnen met een lege keuzelijst?
Wanneer u uw formulier samenstelt, stelt u de
choices
in op een legearray()
: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())); } }
U krijgt dus een lege geselecteerde invoer, zonder keuzes. Deze oplossing werkt voor ChoiceType en al zijn kinderen (EntityType, DocumentType, ...).
Hoe ingediende nieuwe keuzes te accepteren :
Om de nieuwe keuzes te accepteren, moet u ze beschikbaar maken in de keuzelijst van het formulierveld. U kunt uw formulierveld wijzigen afhankelijk van de ingediende gegevens met de gebeurtenis FormEvent :: PRE_SUBMIT.
Dit voorbeeld laat zien hoe het te doen met een standaard KeuzeType:
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)); } ); } }
Uw ingediende keuzes zijn nu toegestane keuzes en de ingebouwde validatie van Symfony ChoiceType zal ze niet meer weigeren.
Als u hetzelfde wilt doen met een ChoiceType-kind (EntityType, DocumentType, ...), moet u de entityManager of de documentManager injecteren en de datatransformatie doen bij het invullen van de nieuwe keuzes.
Vul een selectieveld in afhankelijk van de andere waarde.
Dit is een voorbeeld om te laten zien hoe de toegestane keuzes in een subCategory-selectieveld kunnen worden gewijzigd, afhankelijk van de waarde van het categoriekeuzeveld. Om dat te doen, moet u uw subCategory-keuzes dynamisch maken voor zowel de client als de server.
1. Maak het formulier aan de clientzijde dynamisch voor display / gebruikersinteracties
Voorbeeld van een dynamisch formulier aan de clientzijde (met 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);
});
});
Natuurlijk kunt u de keuzes van een AJAX-oproep krijgen. Dat is niet de bedoeling van dit voorbeeld.
2. Maak het formulier dynamisch aan de serverzijde voor initialisatie / validatie
Voorbeeld van dynamische serverzijde:
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);
}
}