2012-08-01 9 views
6

ho la todolist dove i visualizzazione tre forme di tipo di attivitàCome presentare molteplici forme dello stesso tipo con un pulsante in Symfony2

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

Ora il problema è che ho un pulsante di invio solo. Come posso mantenere queste tre attività all'interno di un controller. e l'utente può aggiungere più moduli anche dinamicamente.

modo ciò che il modo per risolvere questo

+0

si dovrebbe pensare di utilizzare 'jQuery 'per tali compiti. Ti consente l'invio di tutte le forme. –

+0

Acquista ciò che ha jquery da fare con doctrine e persistente. Puoi darmi qualche link in modo che io possa vedere cosa intendi – user825904

risposta

5

creare una classe Form Model - come TaskList - che contiene una collezione di Task s. Quindi creare TaskListType che contiene uno collection di TaskType s. In questo modo avrai un modulo con tutte le attività che desideri.

5

Per motivi di completezza, di seguito è riportato un esempio completo.

È necessario creare un nuovo modello che rappresenti la forma desiderata. Il punto è che probabilmente non vuoi influenzare Doctrine (per esempio vedi doctrine: schema: comando di aggiornamento). Potrebbe provare a creare una tabella per un'entità che non esiste realmente. Per evitare ciò, basta mettere la classe del modello nella cartella Model (\ src \ Acme \ Bundle \ DemoBundle \ Model \ TaskList.php).

Si supponga che il seguente è il vostro TaskType classe form:

<?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'; 
    } 
} 

Questa dovrebbe essere la vostra TaskList classe del modello:

<?php 

namespace Acme\Bundle\DemoBundle\Model; 

use Doctrine\ORM\Mapping as ORM; 
use Doctrine\Common\Collections\ArrayCollection; 

/** 
* Class TaskList 
* @package Acme\Bundle\DemoBundle\Model 
* 
* @ORM\Entity() 
*/ 
class TaskList 
{ 
    /** 
    * @var \Doctrine\Common\Collections\ArrayCollection 
    * @ORM\ManyToMany(targetEntity="\Acme\Bundle\DemoBundle\Entity\Task") 
    */ 
    private $tasks; 

    public function __construct() 
    { 
     $this->tasks = new ArrayCollection(); 
    } 

    /** 
    * @param \Acme\Bundle\DemoBundle\Entity\Task $task 
    * @return $this 
    */ 
    public function addTask(\Acme\Bundle\DemoBundle\Entity\Task $task) 
    { 
     $this->tasks[] = $task; 

     return $this; 
    } 

    /** 
    * @param \Acme\Bundle\DemoBundle\Entity\Task $task 
    * @return $this 
    */ 
    public function removeTask(\Acme\Bundle\DemoBundle\Entity\Task $task) 
    { 
     $this->tasks->remove($task); 

     return $this; 
    } 

    /** 
    * @return ArrayCollection 
    */ 
    public function getTasks() 
    { 
     return $this->tasks; 
    } 

    /** 
    * @param \Doctrine\Common\Collections\Collection $tasks 
    * @return $this 
    */ 
    public function setTasks(\Doctrine\Common\Collections\Collection $tasks) 
    { 
     $this->tasks = $tasks; 

     return $this; 
    } 

    /** 
    * @param \Knp\Component\Pager\Pagination\PaginationInterface $pagination 
    * @return $this 
    */ 
    public function setFromPagination(\Knp\Component\Pager\Pagination\PaginationInterface $pagination) 
    { 
     foreach ($pagination as $task) { 
      $this->addTask($task); 
     } 

     return $this; 
    } 
} 

E seguito troverete la classe TaskListType:

<?php 

namespace Acme\Bundle\DemoBundle\Form; 

use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilderInterface; 
use Symfony\Component\OptionsResolver\OptionsResolverInterface; 

class TaskListType extends AbstractType 
{ 
    /** 
    * @param FormBuilderInterface $builder 
    * @param array $options 
    */ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
      ->add(
       'tasks', 
       'collection', 
       array(
        'type' => new \Acme\Bundle\DemoBundle\Form\TaskType(), 
       ) 
      ) 
      ->add('save', 'submit'); 
    } 

    /** 
    * @param OptionsResolverInterface $resolver 
    */ 
    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(
      array(
       'data_class' => 'Acme\Bundle\DemoBundle\Model\TaskList' 
      ) 
     ); 
    } 

    /** 
    * @return string 
    */ 
    public function getName() 
    { 
     return 'acme_demo_task_list'; 
    } 
} 

E your services.yml (opzionale):

services: 
    acme.demo.form.type.task_list: 
     class: Acme\Bundle\DemoBundle\Form\TaskListType 
     tags: 
      - { name: form.type, alias: acme_demo_task_list } 

e un controller di esempio:

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

Spero che questo aiuta!

4

Abbiamo seguito l'esempio illustrato da "Francesco Casula" e ha funzionato perfettamente.

Per orur fini non abbiamo bisogno di impaginazione, quindi questo è il modo abbiamo riempito la nostra collezione (nella 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'), 
)); 

Per chi ha bisogno di personalizzare l'output delle collezioni di forma, siamo riusciti per accedere alla sottomaschera tramite iterazione su {% for form in forms.children.stocks %}. 'Azioni' è il nome del campo nel nostro costruttore modulo (in StockListType):

public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    $builder 
     ->add(
      'stocks', 'collection', array(
       'type' => new StockType(), 
      ) 
     ) 
     ->add('submit', 'submit') 
    ; 
} 

Questo è quello che abbiamo finito per usare a nostro avviso ramoscello:

{{ 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) }} 
Problemi correlati