2017-08-17 84 views
1

我要求你在Symfony 3中創建特定表單的小建議。Symfony自定義字段或動態表單?

在閱讀Symfony Docs後,我有一些解決方案,但我要求你分享最好的方法來實現這一點。

我需要輸出的形式是這樣的: link for expected example form

正如你看到的我需要一個複選框和一個輸入型的單場constiting。它應該像用戶勾選複選框一樣工作,輸入將被激活。

它應該是自定義字段與FormType作爲父母getParent()方法?也許這個表單應該使用事件監聽器和一些Javascript來動態創建?或者它應該是CollectionType字段(但它如何可以存儲兩種不同的表單字段類型?)或者您可能知道不同的解決方案?

基本上一個字段應該由兩個不同的字段類型相互依賴。

任何幫助,共享知識或一些代碼示例將非常受歡迎。

回答

2

首先,您必須構建一個組成CheckboxType和TextType的自定義FormType。這是服務器端表單部分。

但是,要啓用/禁用動態文本字段,您必須使用Javascript。最後,如果要將結果信息存儲爲單個可爲空的文本字段(如可爲空的varchar),則需要DataTransformer將數據從persistece層轉換爲視圖。

讓我們看到一種FormType的:

<?php 

namespace Form\Type; 

use Form\DataTransformer\NullableTextTransformer; 
use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\Extension\Core\Type\CheckboxType; 
use Symfony\Component\Form\Extension\Core\Type\TextType; 
use Symfony\Component\Form\FormBuilderInterface; 

class NullableTextType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
      ->add('isNotNull', CheckboxType::class) 
      ->add('text', TextType::class, array('required' => false)) 
     ; 

     $builder->addModelTransformer(new NullableTextTransformer()); 
    } 
} 

而現在的變壓器:

<?php 

namespace Form\DataTransformer; 

use Symfony\Component\Form\DataTransformerInterface; 

class NullableTextTransformer implements DataTransformerInterface 
{ 
    public function transform($value) 
    { 
     $nullableText = ['isNotNull' => false, 'text' => null]; 

     if (null !== $value) { 
      $nullableText['isNotNull'] = true; 
      $nullableText['text'] = (string) $value; 
     } 

     return $nullableText; 
    } 

    public function reverseTransform($array) 
    { 
     if (!is_array($array) || empty($array) || !isset($array['isNotNull']) || !isset($array['text'])) { 
      return; 
     } 

     if ($array['isNotNull']) { 
      return (string) $array['text']; 
     } else { 
      return; 
     } 
    } 
} 

一些樹枝自定義字段的形式,主題化:

{% block nullable_text_widget %} 
{% spaceless %} 
    <div class="input-group nullable-text-widget"> 
    <div class="input-group-addon"> 
     {{ form_widget(form.isNotNull, {attr: {class: 'is-not-null-widget'}}) }} 
    </div> 
    {{ form_widget(form.text, {attr: {class: 'text-widget'}}) }} 
    </div> 
{% endspaceless %} 
{% endblock nullable_text_widget %} 

最後,一串JS線來處理前端交互:

$(document).ready(function() { 
    $.each($('body').find('.nullable-text-widget'), function() { 
     syncNullableTextWidget($(this)); 
    }); 
}); 

$(document).on('click', '.nullable-text-widget .is-not-null-widget', function (e) { 
    var $nullableTextWidget = $(e.currentTarget).parents('.nullable-text-widget'); 
    syncNullableTextWidget($nullableTextWidget); 
}); 

function syncNullableTextWidget($widget) 
{ 
    if ($widget.find('.is-not-null-widget').prop('checked')) { 
     $widget.find('.text-widget').prop('disabled', false); 
    } else { 
     $widget.find('.text-widget').prop('disabled', true); 
     $widget.find('.text-widget').val(''); 
    } 
} 
+0

很好的答案!謝謝! – fabtosz

相關問題