如何在symfony2中用一个按钮提交多个相同类型的表单



我有一个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('f3'), $task3);

现在的问题是我只有一个提交按钮。我如何在一个控制器中坚持这三个任务。用户还可以动态添加更多表单。

那么解决这个的方法是什么

创建一个包含Tasks集合的Form Model类(如TaskList),然后创建包含TaskTypes集合的TaskListType。这样,您就可以拥有一个包含任意多任务的表单。

为了完整起见,请在下面找到一个完整的示例。

你应该创建一个代表所需形式的新模型。重点是你可能不想影响条令(例如,参见条令:模式:更新命令)。它可能会尝试为一个并不真正存在的实体创建一个表。为了避免这种情况,只需将模型类放在model文件夹下(\src\Acme\Bundle\DemoBundle\model\TaskList.php)

假设以下是您的TaskType表单类:

<?php
namespace AcmeBundleDemoBundleForm;
use SymfonyComponentFormAbstractType;
use SymfonyComponentFormFormBuilderInterface;
use SymfonyComponentOptionsResolverOptionsResolverInterface;
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' => 'AcmeBundleDemoBundleEntityTask'
            )
        );
    }
    /**
     * @return string
     */
    public function getName()
    {
        return 'acme_demo_task';
    }
}

这应该是您的TaskList模型类:

<?php
namespace AcmeBundleDemoBundleModel;
use DoctrineORMMapping as ORM;
use DoctrineCommonCollectionsArrayCollection;
/**
 * Class TaskList
 * @package AcmeBundleDemoBundleModel
 *
 * @ORMEntity()
 */
class TaskList
{
    /**
     * @var DoctrineCommonCollectionsArrayCollection
     * @ORMManyToMany(targetEntity="AcmeBundleDemoBundleEntityTask")
     */
    private $tasks;
    public function __construct()
    {
        $this->tasks = new ArrayCollection();
    }
    /**
     * @param AcmeBundleDemoBundleEntityTask $task
     * @return $this
     */
    public function addTask(AcmeBundleDemoBundleEntityTask $task)
    {
        $this->tasks[] = $task;
        return $this;
    }
    /**
     * @param AcmeBundleDemoBundleEntityTask $task
     * @return $this
     */
    public function removeTask(AcmeBundleDemoBundleEntityTask $task)
    {
        $this->tasks->remove($task);
        return $this;
    }
    /**
     * @return ArrayCollection
     */
    public function getTasks()
    {
        return $this->tasks;
    }
    /**
     * @param DoctrineCommonCollectionsCollection $tasks
     * @return $this
     */
    public function setTasks(DoctrineCommonCollectionsCollection $tasks)
    {
        $this->tasks = $tasks;
        return $this;
    }
    /**
     * @param KnpComponentPagerPaginationPaginationInterface $pagination
     * @return $this
     */
    public function setFromPagination(KnpComponentPagerPaginationPaginationInterface $pagination)
    {
        foreach ($pagination as $task) {
            $this->addTask($task);
        }
        return $this;
    }
}

并在TaskListType类下面找到:

<?php
namespace AcmeBundleDemoBundleForm;
use SymfonyComponentFormAbstractType;
use SymfonyComponentFormFormBuilderInterface;
use SymfonyComponentOptionsResolverOptionsResolverInterface;
class TaskListType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add(
                'tasks',
                'collection',
                array(
                    'type' => new AcmeBundleDemoBundleFormTaskType(),
                )
            )
            ->add('save', 'submit');
    }
    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(
            array(
                'data_class' => 'AcmeBundleDemoBundleModelTaskList'
            )
        );
    }
    /**
     * @return string
     */
    public function getName()
    {
        return 'acme_demo_task_list';
    }
}

和您的服务。yml(可选):

services:
    acme.demo.form.type.task_list:
        class: AcmeBundleDemoBundleFormTaskListType
        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 DoctrineORMEntityManager $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()
        )
    );
}

我希望这能有所帮助!

我们遵循了"Francesco Casula"展示的示例,它非常完美。

出于其他目的,我们不需要分页,所以这就是我们填充集合(在controller中)的方式:

$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'),
));

对于那些需要自定义表单集合输出的人,我们通过迭代{% for form in forms.children.stocks %}来访问子表单。"Stocks是我们的表单生成器(在StockListType中)中的字段名称:

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) }}

相关内容

  • 没有找到相关文章

最新更新