2014-09-29 6 views
8

Ich versuche, ein Formular zu erstellen, das verschachtelte Sammlungen enthält. Ich weiß nicht, wie ich mit dem JS-Teil umgehen soll, um die Kindersammlung anzuzeigen. Weiß jemand wie ich das machen kann? HierSymfony 2: Umgang mit verschachtelten Sammlungen in Formularen

ist der Code meiner Formen:

class ParentFormType extends AbstractType 
{ 

    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
       ->add('case', 'choice', array(
         'choices' => array(
          'case1' => 'case1', 
          'case2' => 'case2', 
          'case3' => 'case3', 
       ))) 
      ->add ('subForm1', 'collection', array (
      'type' => new Sub1FormType(), 
      'allow_add' => true, 
      'allow_delete' => true, 
      'by_reference' => false, 
      'prototype' => true, 
      )) 

    ; 

     $builder->add('save',"submit") ; 
    } 


    public function setDefaultOptions(OptionsResolverInterface $resolver) { 
    } 

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

class Sub1FormType extends AbstractType 
{ 

    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 

     $builder 
      ->add('fieldSub1',"text") 
      ->add ('childForm1', 'collection', array (
       'type' => new Sub2FormType, 
       'allow_add' => true, 
       'allow_delete' => true, 
       'by_reference' => false, 
       'prototype' => true, 
     )) 
      ; 
    } 


    public function setDefaultOptions(OptionsResolverInterface $resolver) { 

    } 

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

class Sub2FormType extends AbstractType 
{ 

    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 

     $builder 
       ->add('fieldSub2',"text") 
      ; 
    } 


    public function setDefaultOptions(OptionsResolverInterface $resolver) { 

    } 

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

Der Controller:

$form = $this->createForm(new ParentFormType()) ; 
return $this->render('MyBundle:Test:test.html.twig', array(
    'form' => $form->createView() 
)); 

Und hier; der Zweig + js Teil:

{% extends '::base.html.twig' %} 
{% block content %} 

{{ form_start(form) }} 
    <h3>Tags</h3> 
    <ul class="collectionHolder" data-prototype="{{ form_widget(form.subForm1.vars.prototype)|e }}"> 
     {# iterate over each existing tag and render its only field: name #} 
     {% for subForm1 in form.subForm1 %} 
      <li>{{ form_row(subForm1) }} </li> 
      <ul class="collectionHolder" data-prototype="{{ form_widget(subForm2.vars.prototype)|e }}"> 
      {%for subForm2 in subForm1.subForm2 %} 
       <li>{{ form_row(subForm2) }}</li> 
      {% endfor %} 

     {% endfor %} 
    </ul> 
{{ form_end(form) }} 



<script> 
var $collectionHolder; 

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

jQuery(document).ready(function() { 

    function addTagForm($collectionHolder, $newLinkLi) 
    { 
     // Get the data-prototype explained earlier 
     var prototype = $collectionHolder.data('prototype'); 
     // get the new index 
     var index = $collectionHolder.data('index'); 
     // Replace '__name__' in the prototype's HTML to 
     // instead be a number based on how many items we have 
     var newForm = prototype.replace(/__name__/g, index); 

     // increase the index with one for the next item 
     $collectionHolder.data('index', index + 1); 

     // Display the form in the page in an li, before the "Add a tag" link li 
     var $newFormLi = $('<li></li>').append(newForm); 
     $newLinkLi.before($newFormLi); 
    } 


    $collectionHolder = $('.collectionHolder'); 

    $collectionHolder.append($newLinkLi); 

    // count the current form inputs we have (e.g. 2), use that as the new 
    // index when inserting a new item (e.g. 2) 
    $collectionHolder.data('index', $collectionHolder.find(':input').length); 

    $addTagLink.on('click', function(e) { 
     e.preventDefault(); 
     addTagForm($collectionHolder, $newLinkLi); 
    }); 
}); 
</script> 
{% endblock content %} 
+0

Können Sie erklären, was Sie Problem genau ist? Aus der Sicht Ihres Codes haben Sie die Seite "Formularsammlung" bereits in der Symfony-Dokumentation aufgerufen. – ecc

Antwort

4

Ihr Problem ist, dass das Beispiel Javascript nicht auf einmal mehrere Sammlungen zu handhaben geschrieben wurde.

ich eine separate JavaScript-Datei geschrieben habe, die ich immer auch wenn diese Form Sammlungen Handhabung:

// js/form.collection.js 
function FormCollection(div_id) 
{ 
    // keep reference to self in all child functions 
    var self=this; 

    self.construct = function() { 
     // set some shortcuts 
     self.div = $('#'+div_id); 
     self.div.data('index', self.div.find(':input').length); 

     // add delete link to existing children 
     self.div.children().each(function() { 
      self.addDeleteLink($(this)); 
     }); 

     // add click event to the Add new button 
     self.div.next().on('click', function(e) { 
      // prevent the link from creating a "#" on the URL 
      e.preventDefault(); 

      // add a new tag form (see next code block) 
      self.addNew(); 
     }); 
    }; 

    /** 
    * onClick event handler -- adds a new input 
    */ 
    self.addNew = function() { 
     // Get the data-prototype explained earlier 
     var prototype = self.div.data('prototype'); 

     // get the new index 
     var index = self.div.data('index'); 

     // Replace '__name__' in the prototype's HTML to 
     // instead be a number based on how many items we have 
     var newForm = prototype.replace(/__name__/g, index); 

     // increase the index with one for the next item 
     self.div.data('index', index + 1); 

     // Display the form in the page in an li, before the "Add a tag" link li 
     self.div.append($(newForm)); 

     // add a delete link to the new form 
     self.addDeleteLink($(self.div.children(':last-child')[0])); 

     // not a very nice intergration.. but when creating stuff that has help icons, 
     // the popovers will not automatically be instantiated 
     //initHelpPopovers(); 

     return $(newForm); 
    }; 

    /** 
    * add Delete icon after input 
    * @param Element row 
    */ 
    self.addDeleteLink = function (row) { 
     var $removeFormA = $('<a href="#" class="btn btn-danger" tabindex="-1"><i class="entypo-trash"></i></a>'); 
     $(row).find('select').after($removeFormA); 
     row.append($removeFormA); 
     $removeFormA.on('click', function(e) { 
      // prevent the link from creating a "#" on the URL 
      e.preventDefault(); 

      // remove the li for the tag form 
      row.remove(); 
     }); 
    }; 

    self.construct(); 
} 

Innerhalb der gewünschten Vorlage ich dann gezielt nur die Sammlungen von id und fügen Sie instanziiert die Formcollection von id, wie wie:

{% extends '::base.html.twig' %} 
{% block content %} 

{{ form_start(form) }} 
    <h3>Tags</h3> 
    <ul id="col-subform1" data-prototype="{{ form_widget(form.subForm1.vars.prototype)|e }}"> 
     {# iterate over each existing tag and render its only field: name #} 
     {% for subForm1 in form.subForm1 %} 
      <li>{{ form_row(subForm1) }} </li> 
      <ul id="col-subform2" data-prototype="{{ form_widget(subForm2.vars.prototype)|e }}"> 
      {%for subForm2 in subForm1.subForm2 %} 
       <li>{{ form_row(subForm2) }}</li> 
      {% endfor %} 

     {% endfor %} 
    </ul> 
{{ form_end(form) }} 

<script type="text/javascript" src="/js/form.collection.js"></script> 
<script type="text/javascript"> 
    new FormCollection('col-subform1'); 
    new FormCollection('col-subform2'); 
</script> 
+0

Das sieht gut aus! Ich werde diesen Code definitiv implementieren. –

Verwandte Themen