2017-08-17 85 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

相关问题