2012-11-10 15 views
19

Szenario: Ich habe ein Formular mit 2 Auswahlmöglichkeiten. Wenn der Benutzer etwas aus der ersten Auswahl auswählt, wird die zweite Auswahl mit neuen Werten gefüllt. Dieser Teil funktioniert gut.Symfony2: Auswahl ändern mit Ajax und Validierung

Das Formular wird jedoch nicht validiert, da es einige Auswahlmöglichkeiten enthält, die in der ursprünglichen Form nicht zulässig sind.

Form:

<?php 

class MyType extends AbstractType 
{ 
    private $category; 

    public function __construct($category = null) 
    { 
     $this->category = $category; 
    } 

    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder->add('category', 'choice', array(
      'choices' => array(
       'foo' => 'foo', 
       'bar' => 'bar' 
      ) 
     ); 

     $builder->add('template', 'choice', array(
      'choices' => $this->loadChoices() 
     ); 
    } 

    private function loadChoices() 
    { 
     // load them from DB depending on the $this->category 
    } 
} 

zunächst die Kategorie foo. Die Vorlagen für foo werden also geladen und als Auswahl festgelegt. Wenn der Benutzer bar auswählt, werden die Barvorlagen geladen. Aber die Form hat immer noch die Auswahl und validiert nicht.

Was ist der beste Weg, dies zu lösen?

Ein Weg, ich war gefunden, nur die Form, in der Steuerung reinitiate:

<?php 

$form = $this->createForm(new MyType()); 

if ($request->getMethod() === 'POST') { 
    if ($request->request->has($form->getName()) 
     && isset($request->request->get($form->getName())['category'])) { 
      $form = $this->createForm(new MyType($request->request->get($form->getName())['category'])); 
    } 

    // ... 
} 

Dies funktioniert, aber ich kann es nicht testen, weil es IllegalArgumentException wirft, wenn man den Wert und nimmt nur Standard. Gibt es dafür eine bessere Lösung? Danke im Voraus!

+0

Haben Sie versucht, die Validierung Gruppen für jeden Satz von Optionen, die Sie bestätigen müssen eingestellt? Dann können Sie den Validator-Service nur für die Gruppe aufrufen, die für Sie relevant ist. http://symfony.com/doc/2.0/book/forms.html#validation-groups – Xocoatzin

Antwort

20

Ich denke, u haben Ereignisse zu verwenden, um dies zu verwalten, was richtiger Weg ist

public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    $builder->add('category', 'choice', array(
     'choices' => array(
      'foo' => 'foo', 
      'bar' => 'bar' 
     ) 
    )); 

    $ff = $builder->getFormFactory(); 

    // function to add 'template' choice field dynamically 
    $func = function (FormEvent $e) use ($ff) { 
     $data = $e->getData(); 
     $form = $e->getForm(); 
     if ($form->has('template')) { 
      $form->remove('template'); 
     } 

     $cat = isset($data['category'])?$data['category']:null; 

     // here u can populate ur choices in a manner u do it in loadChoices 
     $choices = array('1' => '1', '2' => '2'); 
     if ($cat == 'bar') { 
      $choices = array('3' => '3', '4' => '4'); 
     } 

     $form->add($ff->createNamed('template', 'choice', null, compact('choices'))); 
    }; 

    // Register the function above as EventListener on PreSet and PreBind 
    $builder->addEventListener(FormEvents::PRE_SET_DATA, $func); 
    $builder->addEventListener(FormEvents::PRE_BIND, $func); 
} 
+0

Sorry für späte Antwort hier! Ich werde es heute überprüfen. :) – smottt

+0

Funktioniert perfekt, vielen Dank! – smottt

+0

Ich wurde diesen Link für ein ähnliches Problem empfohlen, das ich versuche zu arbeiten (wo ich AJAX mit 'OnChange' Trigger verwenden wollte). Dieser Weg sieht gut aus, obwohl ich vor dem Ändern alles überprüfen wollte: Kann dies das Formular aktualisieren, um das Dropdown-Menü "Vorlage" aus der Datenbanksuche zu füllen, wenn eine Kategorie ausgewählt wurde, ohne das Formular zu senden? – Bendy