Sök…
Hur man utvidgar ChoiceType, EntityType och DocumentType för att ladda val med AJAX.
I Symfony, den inbyggda ChoiceType (och EntityType eller DocumentType som utvidgar den), arbetar i princip med en konstant vallista.
Om du vill få det till att fungera med ajax-samtal måste du ändra dem för att acceptera eventuella extra val.
Hur börjar jag med en tom vallista?
När du bygger ditt formulär, bara ställa in
choicesalternativet till en tomarray():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())); } }Så du får en tom markerad ingång, utan val. Denna lösning fungerar för ChoiceType och alla hans barn (EntityType, DocumentType, ...).
Hur man accepterar inlämnade nya val :
För att acceptera de nya valen måste du göra dem tillgängliga i formfältets vallista. Du kan ändra ditt formulärfält beroende på skickade data med händelsen FormEvent :: PRE_SUBMIT.
Detta exempel visar hur man gör det med en grundläggande 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)); } ); } }Dina skickade val är nu tillåtna val och Symfony ChoiceType inbyggd validering avvisar dem inte längre.
Om du vill göra samma sak med ett ChoiceType-barn (EntityType, DocumentType, ...), måste du injicera enhetenManager eller documentManager och göra datatransformationen när du fyller i de nya valen.
Bevilja ett markeringsfält beroende på värdet för ett annat.
Detta är ett exempel för att visa hur man ändrar de tillåtna valen i ett fält för underkategori beroende på värdet på fältet för kategoriväljning. För att göra det måste du göra dina underkategori val dynamiska för både klient- och serversidan.
1. Gör formuläret dynamiskt på klientsidan för display / användarinteraktioner
Exempel på dynamisk form av klientsidan (med 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);
});
});
Naturligtvis kan du få valen från ett AJAX-samtal. Det är inte syftet med detta exempel.
2. Gör formuläret dynamiskt på serversidan för initialisering / validering
Exempel på dynamisk form på serversidan:
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);
}
}