如何使用symfony2中的一个按钮提交多个相同类型的表单
我在todolist中显示了三种形式的任务类型如何使用symfony2中的一个按钮提交多个相同类型的表单,symfony,doctrine-orm,Symfony,Doctrine Orm,我在todolist中显示了三种形式的任务类型 $task1 = new Task(); $form1 = $this->createForm(new MyForm('f1'), $task1); $task2 = new Task('fo'); $form2 = $this->createForm(new MyForm('f2'), $task2); $task3 = new Task(); $form3 = $this->createForm(new MyForm('f
$task1 = new Task();
$form1 = $this->createForm(new MyForm('f1'), $task1);
$task2 = new Task('fo');
$form2 = $this->createForm(new MyForm('f2'), $task2);
$task3 = new Task();
$form3 = $this->createForm(new MyForm('f3'), $task3);
现在的问题是我只有一个提交按钮。如何在一个控制器中持久化这三个任务。用户还可以动态添加更多表单
那么解决这个问题的方法是什么呢?创建一个类,比如
TaskList
,它包含任务的集合。然后创建包含TaskType
类型的TaskType
s。这样,您将拥有一个表单,其中包含您想要的任意多个任务。为了完整起见,请在下面找到一个完整的示例
您应该创建一个表示所需表单的新模型。关键是,您可能不想影响条令(例如,请参阅条令:schema:update命令)。它可能会尝试为实际上不存在的实体创建一个表。为了避免这种情况,只需将模型类放在model文件夹下(\src\Acme\Bundle\DemoBundle\model\TaskList.php)
假设以下是TaskType表单类:
<?php
namespace Acme\Bundle\DemoBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class TaskType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('id', null, array('read_only' => true))
->add('name');
}
/**
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(
array(
'data_class' => 'Acme\Bundle\DemoBundle\Entity\Task'
)
);
}
/**
* @return string
*/
public function getName()
{
return 'acme_demo_task';
}
}
和一个示例控制器:
public function indexAction($page)
{
ini_set('xdebug.max_nesting_level', 300); // this might be useful with deeply nested forms
$search = $this->getRequest()->get(
'search',
array(
'name' => '',
'date' => '',
'lang' => $this->container->getParameter('acme_core.default_lang')
)
);
/**
* @var \Doctrine\ORM\EntityManager $em
*/
$em = $this->getDoctrine()->getManager();
$paginator = $this->get('knp_paginator');
$pagination = $paginator->paginate(
$em->getRepository('AcmeDemoBundle:Task')->getQueryFilteringByLangNameAndDate(
$search['lang'],
$search['name'],
$search['date'] != '' ? new \DateTime($search['date']) : null
),
$page,
$this->getRequest()->get('elementsPerPage', 10)
);
$taskList = new TaskList();
$taskList->setFromPagination($pagination);
$form = $this->createForm('acme_demo_task_list', $taskList); // "acme_demo_task_list" has been defined in the services.yml file
$form->handleRequest($this->getRequest());
if ($form->isValid()) {
foreach ($form->getData() as $task) {
$em->merge($task);
}
$em->flush();
}
return $this->render(
'AcmeDemoBundle:Task:index.html.twig',
array(
'search' => $search,
'pagination' => $pagination,
'form' => $form->createView()
)
);
}
我希望这有帮助 我们遵循了“弗朗西斯科·卡苏拉”所展示的考试,考试效果非常好
出于orur目的,我们不需要分页,因此这就是我们填写集合的方式(在控制器中)
:
对于那些需要自定义表单集合输出的用户,我们通过迭代{%For forms in forms.children.stocks%}
来访问子表单Stocks'是表单生成器中字段的名称(在StockListType
中):
这就是我们最终在细枝视图中使用的内容:
{{ form_start(forms) }}
<table class="table table-stripped table-hover">
<thead>
<th>#</th>
<th>Name</th>
<th>Code</th>
<th>Location</th>
<th>Total</th>
<th>Updated Toal</th>
</thead>
<tbody>
{% set counter = 1 %}
{% for form in forms.children.stocks %}
<tr>
<div class="hidden">
{{ form_widget(form.name) }}
{{ form_widget(form.code) }}
{{ form_widget(form.location) }}
{{ form_widget(form.available) }}
{{ form_widget(form.assigned) }}
{{ form_widget(form.minLevel) }}
{{ form_widget(form.type) }}
{{ form_widget(form.colourCode) }}
</div>
<td>{{ counter }}</td>
<td>
{% if form.vars.data.name is defined %}
{{ form.vars.data.name }}
{% endif %}
</td>
<td>
{% if form.vars.data.code is defined %}
{{ form.vars.data.code }}
{% endif %}
</td>
<td>
{% if form.vars.data.location is defined %}
{{ form.vars.data.location }}
{% endif %}
</td>
<td>
{% if form.vars.data.total is defined %}
{{ form.vars.data.total }}
{% endif %}
</td>
<td>{{ form_widget(form.total) }}</td>
</tr>
{% set counter = counter + 1 %}
{% endfor %}
</tbody>
</table>
{{ form_widget(forms.submit) }}
{{ form_end(forms) }}
{{form_start(forms)}
#
名称
代码
位置
全部的
更新至
{%设置计数器=1%}
{forms.children.stocks%}
{{form_小部件(form.name)}
{{form_小部件(form.code)}
{{form_小部件(form.location)}
{{form_小部件(form.available)}
{{form_小部件(form.assigned)}
{{form_小部件(form.minLevel)}
{{form_小部件(form.type)}
{{form_小部件(form.colorCode)}
{{counter}}
{%如果定义了form.vars.data.name%}
{{form.vars.data.name}
{%endif%}
{%如果定义了form.vars.data.code%}
{{form.vars.data.code}
{%endif%}
{%如果定义了form.vars.data.location%}
{{form.vars.data.location}
{%endif%}
{%如果定义了form.vars.data.total%}
{{form.vars.data.total}
{%endif%}
{{form_小部件(form.total)}
{%set counter=计数器+1%}
{%endfor%}
{{form_小部件(forms.submit)}
{{form_end(forms)}}
您应该考虑使用jQuery
执行此类任务。它允许您提交所有表单。购买jquery与信条和坚持有什么关系。你能给我一些链接让我明白你的意思吗
services:
acme.demo.form.type.task_list:
class: Acme\Bundle\DemoBundle\Form\TaskListType
tags:
- { name: form.type, alias: acme_demo_task_list }
public function indexAction($page)
{
ini_set('xdebug.max_nesting_level', 300); // this might be useful with deeply nested forms
$search = $this->getRequest()->get(
'search',
array(
'name' => '',
'date' => '',
'lang' => $this->container->getParameter('acme_core.default_lang')
)
);
/**
* @var \Doctrine\ORM\EntityManager $em
*/
$em = $this->getDoctrine()->getManager();
$paginator = $this->get('knp_paginator');
$pagination = $paginator->paginate(
$em->getRepository('AcmeDemoBundle:Task')->getQueryFilteringByLangNameAndDate(
$search['lang'],
$search['name'],
$search['date'] != '' ? new \DateTime($search['date']) : null
),
$page,
$this->getRequest()->get('elementsPerPage', 10)
);
$taskList = new TaskList();
$taskList->setFromPagination($pagination);
$form = $this->createForm('acme_demo_task_list', $taskList); // "acme_demo_task_list" has been defined in the services.yml file
$form->handleRequest($this->getRequest());
if ($form->isValid()) {
foreach ($form->getData() as $task) {
$em->merge($task);
}
$em->flush();
}
return $this->render(
'AcmeDemoBundle:Task:index.html.twig',
array(
'search' => $search,
'pagination' => $pagination,
'form' => $form->createView()
)
);
}
$entities = $em->getRepository('AcmeBundle:Stock')->findAll();
$stockList = new StockList(); // This is our model, what Francesco called 'TaskList'
foreach ($entities as $entity) {
$stockList->addStock($entity);
}
// StockListType() is what Francesco called TaskListType
$form = $this->createForm(new StockListType(), $stockList, array(
'action' => $this->generateUrl('stock_take_update'),
'method' => 'POST',
'attr' => array('class' => 'form-horizontal'),
));
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add(
'stocks', 'collection', array(
'type' => new StockType(),
)
)
->add('submit', 'submit')
;
}
{{ form_start(forms) }}
<table class="table table-stripped table-hover">
<thead>
<th>#</th>
<th>Name</th>
<th>Code</th>
<th>Location</th>
<th>Total</th>
<th>Updated Toal</th>
</thead>
<tbody>
{% set counter = 1 %}
{% for form in forms.children.stocks %}
<tr>
<div class="hidden">
{{ form_widget(form.name) }}
{{ form_widget(form.code) }}
{{ form_widget(form.location) }}
{{ form_widget(form.available) }}
{{ form_widget(form.assigned) }}
{{ form_widget(form.minLevel) }}
{{ form_widget(form.type) }}
{{ form_widget(form.colourCode) }}
</div>
<td>{{ counter }}</td>
<td>
{% if form.vars.data.name is defined %}
{{ form.vars.data.name }}
{% endif %}
</td>
<td>
{% if form.vars.data.code is defined %}
{{ form.vars.data.code }}
{% endif %}
</td>
<td>
{% if form.vars.data.location is defined %}
{{ form.vars.data.location }}
{% endif %}
</td>
<td>
{% if form.vars.data.total is defined %}
{{ form.vars.data.total }}
{% endif %}
</td>
<td>{{ form_widget(form.total) }}</td>
</tr>
{% set counter = counter + 1 %}
{% endfor %}
</tbody>
</table>
{{ form_widget(forms.submit) }}
{{ form_end(forms) }}