Propel Symfony和spreep:生成动态表单
我正在使用Symfony-2.1和Propel开发一个基本CRUD应用程序。理想情况下,我的模型将在推进XML模式中定义,GUI将自动更新以反映更改。我认为在我规定的时间限制内这是不可能的,但我正在尽可能的接近 我的第一个折衷方案是手工创建表单类型,因为推进表单类型生成器相当初级。但是为了保持手动采用的水平,例如,在添加新的模型类型时,我想通过定义自定义表单类型来完全解决以下问题: 我有一个中等复杂的标题模型,它与表示历史出版物的主要、次要和简短标题的标题片段模型有一对多的关系。 在编辑标题的HTML表单中,我实现了标准的AddOne行为,以允许添加另一个标题片段,如中所述 cookbook解决方案为表单元素提出了一个列表结构,我添加了两个JavaScript指示符类来触发该表单元素上的jQuery控件元素生成代码:Propel Symfony和spreep:生成动态表单,propel,symfony-2.1,Propel,Symfony 2.1,我正在使用Symfony-2.1和Propel开发一个基本CRUD应用程序。理想情况下,我的模型将在推进XML模式中定义,GUI将自动更新以反映更改。我认为在我规定的时间限制内这是不可能的,但我正在尽可能的接近 我的第一个折衷方案是手工创建表单类型,因为推进表单类型生成器相当初级。但是为了保持手动采用的水平,例如,在添加新的模型类型时,我想通过定义自定义表单类型来完全解决以下问题: 我有一个中等复杂的标题模型,它与表示历史出版物的主要、次要和简短标题的标题片段模型有一对多的关系。 在编辑标题的H
<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>
现在,我必须通过sortableCollection小部件块来扩充默认的symfony表单主题form_div_layout.html.twig,以强制将我的集合呈现为列表,并将一些JavaScript指示符类附加到列表中,如代码示例1所示
问题在于,在模板中,form.titleFragments依赖于模型,并且始终依赖于模型,因为数据需要绑定到标题模型的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”)传递给模板,因为自版本1.2以来,twig支持使用属性函数动态访问对象属性
有人知道如何从自定义表单类型到细枝模板获取数据吗?那没问题,不过这当然是多余的,而且有点笨拙
$builder->add('titleFragments',
new Form\DerivedType\SortableCollectionType(), array(
'type' => new TitlefragmentType(),
'options' => array('collectionPropertyName' => 'titleFragments'),
我没有发现Symfony API特别有用。要将数据传递给视图,可以使用表单类型的finishView方法
public function finishView(FormView $view, FormInterface $form, array $options){
$view->vars['modelClass'] = $this->modelClass;
}
因为data_类是在表单类型上定义的,所以我甚至可以自动计算这个值。如果集合包含嵌套类型,我还会自动覆盖原型元素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 %}
{% 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 %}