2017-08-09 102 views
0

我一直在使用Symfony 3,直到現在我只生成簡單的表單。現在,我想生成一個更復雜,動態的形式和一些幫助,將不勝感激。如何在Symfony中創建動態級聯表單?

我的網站引用了與類別相關的產品。因此,我創建了一個ProductCategory實體,它依賴於Doctrine擴展。因此,實際產品是樹結構的葉子,其他節點(即至少有一個孩子的節點)只是產品類別。

這種結構的一個例子是這樣:

Food 
     Fruits 
      Apple 
      Pear 
     Vegetables 
      Pepper 
      Zucchini 
Vehicle 
     Car 
     Bike 

在這個例子中,產品是蘋果,梨,辣椒,西葫蘆,汽車和自行車。

我想生成一個旨在選擇產品的表單。預期的行爲應該是這樣一個:

  • 最初,用戶看到與根類別(這裏的食物和車輛)
  • 當用戶選擇一個類別,一個新的下拉菜單出現低於前一個下拉列表一個填充了與先前選擇的類別相對應的子類別(例如,如果已選擇食品,則選擇水果和蔬菜)
  • 該過程應該重新開始,直到用戶選擇產品,即樹結構的葉子。

爲了使表格有效,用戶必須選擇了產品(葉)。

現在,我已經能夠通過下拉菜單生成初始表格,其中列出了根類別。以下是用於執行此操作的代碼。

use Symfony\Bridge\Doctrine\Form\Type\EntityType; 
use AppBundle\Entity\ProductCategory; 
use AppBundle\Repository\ProductCategoryRepository; 
  
class ProductType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
            $builder->add('productCategory',EntityType::class,array(
                'class'         => 'AppBundle:ProductCategory', 
                'query_builder' => function(ProductCategoryRepository $repository){ 
                        return $repository->getRootNodesQueryBuilder(); 
                }, 
                'label'         => 'product category', 
                'choice_label'  => 'name', 
                'choice_value'  => 'name', 
                'multiple'      => false, 
                'expanded'      => false, 
                'required'      => true 
            )); 
    } 
  
  
    public function configureOptions(OptionsResolver $resolver) 
    { 
        $resolver->setDefaults(array(
            'data_class' => Product::class, 
            'method' => 'POST', 
        )); 
    } 
} 

由此看來,這個想法是使用AJAX和jQuery到:

  • (當前)選擇的類別發送到服務器,使用上下拉的「改變」事件
  • 生成並顯示低於前一個新的下拉列表中,用足夠的

不過,我不知道如何修改ProductTypeç爲了生成基於當前選擇的類別的新的EntityType字段,然後發回更新的表格以便允許其通過jQuery顯示。

因此,任何幫助或建議將是非常值得歡迎的,以便在構建這個動態表單方面取得進展!

+0

看看這可以幫助你https://symfony.com/doc/current/form/dynamic_form_modification.html#dynamic-generation-for-已提交表格 – JGrinon

回答

0

如果我理解你的問題是正確的,那麼你需要獲得給定類別的子類別。你可以把它作爲一個選項,以ProductType

use Symfony\Bridge\Doctrine\Form\Type\EntityType; 
use AppBundle\Entity\ProductCategory; 
use AppBundle\Repository\ProductCategoryRepository; 
  
class ProductType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
      $category = $options['category']; 

            $builder->add('productCategory',EntityType::class,array(
                'class'         => 'AppBundle:ProductCategory', 
                'query_builder' => function(ProductCategoryRepository $repository) use ($category){ 
                        return $repository->getRootNodesQueryBuilder($category); 
                }, 
                'label'         => 'product category', 
                'choice_label'  => 'name', 
                'choice_value'  => 'name', 
                'multiple'      => false, 
                'expanded'      => false, 
                'required'      => true 
            )); 
    } 
  
  
    public function configureOptions(OptionsResolver $resolver) 
    { 
        $resolver->setDefaults(array(
            'data_class' => Product::class, 
            'method' => 'POST', 
      'category' => null 
        )); 
    } 
} 

getRootNodesQueryBuilder()可以解析基於通過類別子類別。在控制器(您收到AJAX請求),你可以使用它像

$form = $this->createForm(ProductType::class, $product, [ 
     'category' => $request->get('category') 
]); 
+0

感謝您的幫助,我會走這條路。但是,我有一個關於我的控制器的問題:如何檢測表單是否已完全提交(也是通過AJAX完成的),還是僅發送了部分數據(即新選擇的類別)?如果可能的話,我想在這兩種情況下使用相同的控制器。 –

+0

我建議不要提交部分數據。您可以將此字段值發佈到ajax數據中,然後獲取請求。因此您不必擔心部分或全部數據。如果你真的需要檢查,你可以檢查一些其他領域,如果它是在發佈數據 –

+0

在ajax發佈單個字段到控制器的問題是$ form-> handleRequest($ request)拋出一個錯誤,因爲我猜測它期望所有字段的數據(不僅是通過ajax發送的類別)。在發佈單個字段的情況下,我想我不會使用handleRequest方法...但在這種情況下,我不知道如何更新表單,因爲表單未提交(並且基於更新在POST_SUBMIT事件上...)。 –