symfony 2 中的嵌套表单集合
Nested form Collection in symfony 2
我有一个包含集合类型字段的表单,在集合类型字段中还有一个集合类型字段。我必须在树枝中添加嵌套表单字段,但我无法填充表单字段,也无法找到它显示的示例,如何使用 JQuery.
填充嵌套字段
First form class :
class SurveyType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add(
'questiongroups',
CollectionType::class,
[
'entry_type' => QuestionGroupType::class,
'allow_add' => true,
'allow_delete' => true,
'entry_options' => [
'submitOption' => $options['submitOption']
]
]
);
}
Second form class which have another collection type field :
class QuestionGroupType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add(
'questions',
CollectionType::class,
[
'entry_type' => QuestionType::class,
'allow_add' => true,
'allow_delete' => true,
'entry_options' => [
'submitOption' => $options['submitOption']
],
'prototype_name' => '__que__'
]
);
}
On twig I its like this:
<ul id="questiongroups-field-list" data-prototype-question="{{ form_widget(form.questiongroups.vars.prototype.children['questions'].vars.prototype)|e }}"
data-prototype="{{ form_widget(form.questiongroups.vars.prototype)|e}}"
data-widget-tags="{{'<li></li>'|e}}">
我的 Jquery 用于填充字段:
$(document).on('click', '.add-another-collection-widget', function(e){
var list = $($(this).attr('data-list'));
var counter = list.data('widget-counter') | list.children().length;
var newWidget = list.attr('data-prototype');
newWidget = newWidget.replace(/__name__/g, counter);
console.log(newWidget);
counter++;
list.data('widget-counter', counter);
var newElem = jQuery(list.attr('data-widget-tags')).html(newWidget);
newElem.appendTo(list);
addTagFormDeleteLink(newElem);
});
function addTagFormDeleteLink($tagFormLi) {
var $addQuestionButton = $('<button class="button" type="button">Add Question</button>');
var $removeFormButton = $('<button class="alert button" type="button">Delete Group</button>');
$tagFormLi.append($addQuestionButton);
$tagFormLi.append($removeFormButton);
$removeFormButton.on('click', function(e) {
// remove the li for the tag form
$tagFormLi.remove();
});
$addQuestionButton.on('click', function(){
var list = $('#questiongroups-field-list');
var counter = list.data('widget-counter') | list.children().length;
var newWidget = list.attr('data-prototype-question');
newWidget = newWidget.replace(/__name__/g, counter);
counter++;
list.data('widget-counter', counter);
$tagFormLi.append(newWidget);
});
}
仔细检查原型变量后。这就是我将单一表单集合的代码修改为嵌套表单集合的方式:
原型字段更改:
<ul id="questiongroups-field-list" data-prototype-question = "{{ form_widget(form.questiongroups.vars.prototype.children['questions'].vars.prototype)|e }}"
data-prototype="{{ form_widget(form.questiongroups.vars.prototype)|e}}"
data-widget-tags="{{'<li></li>'|e}}" data-tag-list = "{{ '<ul class="question-list"></ul>' |e}}">
下面是Jquery代码:
$(document).on('click', '.add-questiongroup[data-target]', function(event) {
var collectionHolder = $($(this).attr('data-target'));
if (!collectionHolder.attr('data-counter')) {
collectionHolder.attr('data-counter', collectionHolder.children().length);
}
var prototype = collectionHolder.attr('data-prototype');
var form = prototype.replace(/__name__/g, collectionHolder.attr('data-counter'));
newWidget = $(collectionHolder.attr('data-widget-tags')).html(form);
newWidget.append(collectionHolder.attr('data-tag-list'));
collectionHolder.attr('data-counter', Number(collectionHolder.attr('data-counter')) + 1);
collectionHolder.append(newWidget);
var questionPrototype = collectionHolder.attr('data-prototype-question');
var counter = collectionHolder.attr('data-counter');
newWidget.attr('data-counter', counter);
addTagFormDeleteLink(newWidget);
$('.option-min, .option-max').parent().hide();
event && event.preventDefault();
});
function addTagFormDeleteLink(newWidget) {
$removeFormButton = $('<button type="button" class="alert button">Delete Group</button>');
$addQuestionButton = $('<button type="button" class="button">Add Question</button><br>');
$removeQuestion = $('<button type="button" class="alert button deleteQuebtn">Delete Question</button>');
newWidget.append($addQuestionButton);
newWidget.append($removeFormButton);
$removeFormButton.on('click', function(e) {
newWidget.remove();
});
$addQuestionButton.on('click', function(e){
$holder = $('#questiongroups-field-list');
$question = $holder.attr('data-prototype-question');
$questionHolder = newWidget.find('ul');
var counter = $questionHolder.children().length;
var form = $question.replace(/__name__/g, $holder.attr('data-counter')-1).replace(/__que__/g, counter++);
var newQuestion = $($holder.attr('data-widget-tags')).html(form);
$questionHolder.append(newQuestion);
});
}
在这种情况下,表单是一种痛苦
我通常会解决,在这种情况下,我会以另一种方式为您建议:
- 每一个 html 显示一个集合的单个项目是通过 AJAX 加载的(我称之为 "subform")
- 因此,当我需要在表单中添加集合中的一项时,我会这样做:
/**
* @Route("edit/break-evens/_form", name="admin_ride_edit_ride_break_evens_subform", options={"expose"=true}, methods={"GET"})
*/
public function _formAction()
{
$entity = new Ride();
$entity->addBreakEven(new BreakEven());
$form = $this->createForm(
RideType::class,
$entity
);
$form = $form->get('breakEvens')[0];
return $this->render('AdminBundle:Ride:_edit.html.twig', [
'form' => $form->createView(),
]);
}
其中:
Ride
是 1:n 和 BreakEven
,也就是说 breakEvens
是 RideType
形式的集合
所以,当我想添加一个项目时:
- 我调用上面的动作
- 我创建了一个 "full" 表单,添加了一个感兴趣的集合的项目 (
new BreakEven()
)
- 我只为集合中的第一个对象创建视图
- 然后加载时用js改变表单域的编号
当然,如果你有多个集合,事情会变得更困难,但你可以考虑这个概念
我有一个包含集合类型字段的表单,在集合类型字段中还有一个集合类型字段。我必须在树枝中添加嵌套表单字段,但我无法填充表单字段,也无法找到它显示的示例,如何使用 JQuery.
填充嵌套字段First form class :
class SurveyType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add(
'questiongroups',
CollectionType::class,
[
'entry_type' => QuestionGroupType::class,
'allow_add' => true,
'allow_delete' => true,
'entry_options' => [
'submitOption' => $options['submitOption']
]
]
);
}
Second form class which have another collection type field :
class QuestionGroupType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add(
'questions',
CollectionType::class,
[
'entry_type' => QuestionType::class,
'allow_add' => true,
'allow_delete' => true,
'entry_options' => [
'submitOption' => $options['submitOption']
],
'prototype_name' => '__que__'
]
);
}
On twig I its like this:
<ul id="questiongroups-field-list" data-prototype-question="{{ form_widget(form.questiongroups.vars.prototype.children['questions'].vars.prototype)|e }}"
data-prototype="{{ form_widget(form.questiongroups.vars.prototype)|e}}"
data-widget-tags="{{'<li></li>'|e}}">
我的 Jquery 用于填充字段:
$(document).on('click', '.add-another-collection-widget', function(e){
var list = $($(this).attr('data-list'));
var counter = list.data('widget-counter') | list.children().length;
var newWidget = list.attr('data-prototype');
newWidget = newWidget.replace(/__name__/g, counter);
console.log(newWidget);
counter++;
list.data('widget-counter', counter);
var newElem = jQuery(list.attr('data-widget-tags')).html(newWidget);
newElem.appendTo(list);
addTagFormDeleteLink(newElem);
});
function addTagFormDeleteLink($tagFormLi) {
var $addQuestionButton = $('<button class="button" type="button">Add Question</button>');
var $removeFormButton = $('<button class="alert button" type="button">Delete Group</button>');
$tagFormLi.append($addQuestionButton);
$tagFormLi.append($removeFormButton);
$removeFormButton.on('click', function(e) {
// remove the li for the tag form
$tagFormLi.remove();
});
$addQuestionButton.on('click', function(){
var list = $('#questiongroups-field-list');
var counter = list.data('widget-counter') | list.children().length;
var newWidget = list.attr('data-prototype-question');
newWidget = newWidget.replace(/__name__/g, counter);
counter++;
list.data('widget-counter', counter);
$tagFormLi.append(newWidget);
});
}
仔细检查原型变量后。这就是我将单一表单集合的代码修改为嵌套表单集合的方式: 原型字段更改:
<ul id="questiongroups-field-list" data-prototype-question = "{{ form_widget(form.questiongroups.vars.prototype.children['questions'].vars.prototype)|e }}"
data-prototype="{{ form_widget(form.questiongroups.vars.prototype)|e}}"
data-widget-tags="{{'<li></li>'|e}}" data-tag-list = "{{ '<ul class="question-list"></ul>' |e}}">
下面是Jquery代码:
$(document).on('click', '.add-questiongroup[data-target]', function(event) {
var collectionHolder = $($(this).attr('data-target'));
if (!collectionHolder.attr('data-counter')) {
collectionHolder.attr('data-counter', collectionHolder.children().length);
}
var prototype = collectionHolder.attr('data-prototype');
var form = prototype.replace(/__name__/g, collectionHolder.attr('data-counter'));
newWidget = $(collectionHolder.attr('data-widget-tags')).html(form);
newWidget.append(collectionHolder.attr('data-tag-list'));
collectionHolder.attr('data-counter', Number(collectionHolder.attr('data-counter')) + 1);
collectionHolder.append(newWidget);
var questionPrototype = collectionHolder.attr('data-prototype-question');
var counter = collectionHolder.attr('data-counter');
newWidget.attr('data-counter', counter);
addTagFormDeleteLink(newWidget);
$('.option-min, .option-max').parent().hide();
event && event.preventDefault();
});
function addTagFormDeleteLink(newWidget) {
$removeFormButton = $('<button type="button" class="alert button">Delete Group</button>');
$addQuestionButton = $('<button type="button" class="button">Add Question</button><br>');
$removeQuestion = $('<button type="button" class="alert button deleteQuebtn">Delete Question</button>');
newWidget.append($addQuestionButton);
newWidget.append($removeFormButton);
$removeFormButton.on('click', function(e) {
newWidget.remove();
});
$addQuestionButton.on('click', function(e){
$holder = $('#questiongroups-field-list');
$question = $holder.attr('data-prototype-question');
$questionHolder = newWidget.find('ul');
var counter = $questionHolder.children().length;
var form = $question.replace(/__name__/g, $holder.attr('data-counter')-1).replace(/__que__/g, counter++);
var newQuestion = $($holder.attr('data-widget-tags')).html(form);
$questionHolder.append(newQuestion);
});
}
在这种情况下,表单是一种痛苦
我通常会解决,在这种情况下,我会以另一种方式为您建议:
- 每一个 html 显示一个集合的单个项目是通过 AJAX 加载的(我称之为 "subform")
- 因此,当我需要在表单中添加集合中的一项时,我会这样做:
/**
* @Route("edit/break-evens/_form", name="admin_ride_edit_ride_break_evens_subform", options={"expose"=true}, methods={"GET"})
*/
public function _formAction()
{
$entity = new Ride();
$entity->addBreakEven(new BreakEven());
$form = $this->createForm(
RideType::class,
$entity
);
$form = $form->get('breakEvens')[0];
return $this->render('AdminBundle:Ride:_edit.html.twig', [
'form' => $form->createView(),
]);
}
其中:
Ride
是 1:n 和BreakEven
,也就是说breakEvens
是RideType
形式的集合
所以,当我想添加一个项目时:
- 我调用上面的动作
- 我创建了一个 "full" 表单,添加了一个感兴趣的集合的项目 (
new BreakEven()
) - 我只为集合中的第一个对象创建视图
- 然后加载时用js改变表单域的编号
当然,如果你有多个集合,事情会变得更困难,但你可以考虑这个概念