【问题标题】:Symfony and Propel: Generating Dynamic FormsSymfony 和 Propel:生成动态表单
【发布时间】:2012-11-30 06:41:40
【问题描述】:

我正在使用 Symfony-2.1 和 Propel 开发一个基本的 CRUD 应用程序。理想情况下,我的模型将在推进 XML 模式中定义,并且 GUI 将自动更新以反映更改。我认为这在我给定的时间限制内是不可能的,但我正在努力尽可能接近。

我的第一个折衷方案是手动创建表单类型,因为推进表单类型生成器相当初级。但是为了保持手动采用的水平(例如,在添加新模型类型时),我想完全通过自定义表单类型的定义来解决以下问题:

我有一个中等复杂的 Title 模型,它与 TitleFragment 模型具有一对多的关系(代表历史出版物的主标题、副标题和短标题)。 在我编辑标题的 HTML 表单中,我实现了标准的“添加一个”行为以允许添加另一个 TitleFragment(如 symfony cookbook 中所述)。

cookbook 解决方案为表单元素提出了一个列表结构,我添加了两个 JavaScript 指示器类来触发该表单元素上的 jQuery 控件元素生成代码:

<form [...]>
 <ol class="collection-editor collection-sortable" 
      data-prototype="{{ form_widget(form.titleFragments.vars.prototype)|e }}">
    {% for titleFragment in form.titleFragments %}
        <li>
        {{ form_widget(titleFragment) }}
        </li>
    {% endfor %}
  </ol>
  [...]
</form>

我想通过对自定义表单类型使用 symfony 表单主题技术来自动生成该标记。为此,我继承了 symfony 集合表单类型,只是更改了它的名称以使我的自定义表单主题适用于该表单:

class SortableCollectionType extends \Symfony\Component\Form\Extension\Core\Type\CollectionType {
    public function getName() {
        return 'sortableCollection'; 
    }
}

现在,我必须通过 sortableCollection_widget 块来增加默认的 symfony 表单主题 (form_div_layout.html.twig) 以强制将我的集合呈现为列表并将一些 JavaScript 指示器类附加到列表中(如代码示例 #1 中所示) )。

问题在于,在模板中,form.titleFragments 依赖于模型(并且将始终依赖于模型,因为数据需要绑定到 Title 模型的 TitleFragments 的底层集合)。

class TitleType extends BaseAbstractType {

public function buildForm(FormBuilderInterface $builder, array $options) {

    $builder->add('titleFragments', // no choice for a generic name here

      new Form\DerivedType\SortableCollectionType(), array( 
        'type' => new TitlefragmentType(),
        'allow_add' => true,
        'by_reference' => false,
    ));
}
}

我考虑过将属性名称(例如“titleFragments”)传递给模板,因为 twig 从 1.2 版本开始支持对对象属性的动态访问(使用属性函数)。

有人知道如何从我的自定义表单类型一直获取数据到树枝模板吗?那没关系。虽然这当然是多余的而且有点笨拙。

    $builder->add('titleFragments', 
      new Form\DerivedType\SortableCollectionType(), array( 
        'type' => new TitlefragmentType(),
        'options' => array('collectionPropertyName' => 'titleFragments'),

我没有发现 form builder 的 Symfony API 特别有用。

【问题讨论】:

    标签: propel symfony-2.1


    【解决方案1】:

    要将数据传递给视图,可以使用表单类型的finishView方法。

    public function finishView(FormView $view, FormInterface $form, array $options){
            $view->vars['modelClass'] = $this->modelClass;
    }
    

    由于 data_class 是在表单类型上定义的,我什至可以自动计算这个值。如果集合包含嵌套类型,我还会自动覆盖原型元素 id 占位符 (prototypeName)。

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        parent::buildForm($builder, $options);
    
        // extract unqualified class name and pass it to the view
        // this allows more accurate control elements (instead of "add component",
        // one can use "add modelClass")
        $dataClassStr = $options['type']->getOption('data_class');
        $parts = explode('\\', $dataClassStr);
        $this->modelClass = array_pop($parts);
    
        $prototypeName = '__' . $this->modelClass . 'ID__';
    
        if ($options['allow_add'] && $options['prototype']) {
            $prototype = $builder->create($prototypeName, $options['type'], array_replace(array(
                'label' => $options['prototype_name'] . 'label__',
            ), $options['options']));
            $builder->setAttribute('prototype', $prototype->getForm());
        }
    }
    

    在 twig 模板中,传递给视图的数据可通过 form.vars 变量获得。

    {% block sortableCollection_widget %}
    {% spaceless %}
    
        {# [...] code copied from the default collection widget #}
    
        <a href="#" class="sortableCollectionWidget add-entity">
            {{ form.vars.modelClass|trans }} add one
        </a>
    
        {# For the javascript to have access to the translated modelClass name.
           The up and down sortable controls need this to be more expressive.   #}
    
        <input type="hidden" name="modelClassName" value="{{ form.vars.modelClass }}"/>
    
    {% endspaceless %}
    {% endblock %}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-04
      • 2012-11-15
      • 1970-01-01
      • 1970-01-01
      • 2023-03-10
      相关资源
      最近更新 更多