Sergios.Soft
Sergios.Soft

Reputation: 3

How to render collections of forms

I have problem with rendering forms in Twig. I'm trying to embed a collection of forms. When I render the collection, it is not shown, while it is shown the name of form. The aim was to make the forms with an add button to add at runtime the form for each element of the collection. I get a look to the Symfony Docs and I think I followed it step by step.

This is my controller:

function new_resultAction($id)
{
    $em = $this->getDoctrine()->getEntityManager();

    $test = $em->getRepository('LadelaOdeskTesterBundle:Test')->find($id);
    $categories =  
      $em->getRepository('LadelaOdeskTesterBundle:Category')->findByTest($test);
    if (!$test) {
        throw $this->createNotFoundException('Unable to find Test entity.');
    } 

    $resultCategory = new Category();


    $form = $this->createForm(new CategoryType() , $resultCategory);

    $request = $this->getRequest();

    if ('POST' === $request->getMethod()) {

        $form->bindRequest($request);

        if ($form->isValid()) {

            $em->persist($resultCategory);                
            $em->flush();

            $this->get('session')->setFlash('success', 'New result Categories were 
          saved!');
            return $this->redirect($this->generateUrl('questions', array(
                'id' => $resultCategory->getId(),
            )));
        }
    }                 
  return array(
        'test' => $test,
        'categories' =>$categories,

        'form' => $form->createView(), 


      );

}

My forms:

 class ResultCategoryType extends AbstractType
    {
  public function buildForm(FormBuilderInterface $builder, array $options)
   {
    $builder->add('value', 'integer');
    $builder->add('category', 'entity', array(
            'class'         => 'Ladela\OdeskTesterBundle\Entity\Category',
            'query_builder' => function ($repository) { return 
     $repository->createQueryBuilder('p')->orderBy('p.name', 'ASC'); },
             'property' => 'name' ,
               'expanded' => false ,
               'multiple' => false , ));


 }

  public function setDefaultOptions(OptionsResolverInterface $resolver)
  {
    $resolver->setDefaults(array(
        'data_class' => 'Ladela\OdeskTesterBundle\Entity\ResultCategory'
    ));
  }

  public function getName()
{
    return 'ResultCategory';
}
 }

 class CategoryType extends AbstractType
 {
  public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('name')
        ->add('resultCategories','collection', array(
            'type' => new ResultCategoryType(),
            'allow_add' => true,
            'by_reference' => false,
            'prototype' => true,

        ))
    ;
}

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => 'Ladela\OdeskTesterBundle\Entity\Category'
    ));
}

public function getName()
{
    return 'category';
}

}

And my twig file:

<form method="post" action="{{ path('questions',{'id': test.id })  }}" {{   
  form_enctype(form) }} >    

  <ul class="tags" data-prototype="{{ 
  form_widget(form.resultCategories.vars.prototype)|e 
   }}">
    {# iterate over each existing tag and render its only field: name #}
    {% for ResultCategory in form.resultCategories %}
        <li>{{ form_row(ResultCategory.category) }}</li>
    {% endfor %}
<a href="#" class="add_tag_link">Add a tag</a>

</ul>        
{{ form_rest(form) }}{# form.items's prototype is rendered twice #}
{{ form_errors(form) }}
<input type="submit" value ="add" />
</form> 

 {% block javascripts %}


<script type="text/javascript">
// Get the div that holds the collection of tags
var collectionHolder = $('ul.tags');

 // setup an "add a tag" link
   var $addTagLink = $('<a href="#" class="add_tag_link">Add a tag</a>');
  var $newLinkLi = $('<li></li>').append($addTagLink);

jQuery(document).ready(function() {
// add the "add a tag" anchor and li to the tags ul
collectionHolder.append($newLinkLi);

$addTagLink.on('click', function(e) {
    // prevent the link from creating a "#" on the URL
    e.preventDefault();

    // add a new tag form (see next code block)
    addTagForm(collectionHolder, $newLinkLi);
   });
 });
  // Get the div that holds the collection of tags
 var collectionHolder = $('ul.tags');

  // setup an "add a tag" link
 var $addTagLink = $('<a href="#" class="add_tag_link">Add a tag</a>');
 var $newLinkLi = $('<li></li>').append($addTagLink);

  jQuery(document).ready(function() {
 // add the "add a tag" anchor and li to the tags ul
  collectionHolder.append($newLinkLi);

 $addTagLink.on('click', function(e) {
    // prevent the link from creating a "#" on the URL
    e.preventDefault();

    // add a new tag form (see next code block)
    addTagForm(collectionHolder, $newLinkLi);
   });
  });

  {% endblock %}

Upvotes: 0

Views: 4385

Answers (1)

JeanValjean
JeanValjean

Reputation: 17713

The collection of forms is not rendered since you don't initiate it! See the official docs. There are "dummy" tags object used to create the tag forms.

Upvotes: 2

Related Questions