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
choices
alternativet 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);
}
}