2012-11-10 33 views
19

Tình huống: Tôi có biểu mẫu với 2 lựa chọn. Khi người dùng chọn một cái gì đó từ lựa chọn đầu tiên, lựa chọn thứ hai được điền bằng các giá trị mới. Phần này hoạt động tốt.Symfony2: Thay đổi lựa chọn bằng ajax và xác nhận

Nhưng biểu mẫu không được xác thực vì nó chứa một số lựa chọn không được phép ở dạng ban đầu.

Mẫu:

<?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 
    } 
} 

Ban đầu loại là foo. Vì vậy, các mẫu cho foo được tải và đặt làm lựa chọn. Nhưng nếu người dùng chọn bar, các mẫu thanh sẽ được tải. Nhưng biểu mẫu vẫn có các lựa chọn foo và không xác thực.

Cách tốt nhất để giải quyết vấn đề này là gì?

Một cách tôi tìm thấy là chỉ cần bắt đầu lại mẫu tại bộ điều khiển:

<?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'])); 
    } 

    // ... 
} 

này hoạt động, nhưng tôi không thể kiểm tra nó bởi vì nó ném IllegalArgumentException khi thiết lập các giá trị và chỉ thừa nhận mặc định. Có giải pháp nào tốt hơn cho việc này không? Cảm ơn trước!

+0

Bạn đã cố gắng để thiết lập nhóm xác nhận cho mỗi bộ tùy chọn bạn cần phải xác nhận? Sau đó, bạn có thể gọi dịch vụ trình xác thực chỉ trên nhóm có liên quan đến bạn. http://symfony.com/doc/2.0/book/forms.html#validation-groups – Xocoatzin

Trả lời

20

Tôi nghĩ u phải sử dụng sự kiện để quản lý này, đó là cách chính xác hơn

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

Xin lỗi vì đã trả lời muộn ở đây! Tôi sẽ kiểm tra nó ngày hôm nay. :) – smottt

+0

Hoạt động hoàn hảo, cảm ơn bạn rất nhiều! – smottt

+0

Tôi đã được đề nghị liên kết này cho một vấn đề tương tự tôi đang cố gắng để có được làm việc (nơi tôi đã tìm cách sử dụng AJAX với kích hoạt 'onChange'). Cách này có vẻ tốt, mặc dù tôi muốn kiểm tra trước khi thay đổi mọi thứ: Có thể làm mới biểu mẫu này để điền vào trình đơn thả xuống 'template' từ tra cứu cơ sở dữ liệu khi một Danh mục đã được chọn mà không gửi biểu mẫu không? – Bendy

Các vấn đề liên quan