Este post tiene el código necesario para implementar el tipo colección (collection). Lo que se busca es embeber uno o más formularios dentro de otro formulario.
Tenemos dos entidades relacionadas Factura e Item.
Una Factura contiene Items.
Los Items pertenecen a Facturas.
En el formulario de la Factura:
// ../src/Acme/TestBundle/Form/FacturaType.php
//..
$builder
//..otros campos
->add('items', 'collection', array(
'type' => new ItemType(),
'by_reference' => false,
'allow_add' => true, //Permite agregar nuevas colecciones
'allow_delete' => true, //Permite eliminar colecciones
'label' => 'Items',
'options' => array('label' => false)
))
;
En la entidad Factura:
// ../src/Acme/TestBundle/Entity/Factura.php
//..
/**
* @var Items
*
* @ORM\OneToMany(targetEntity="Acme\TestBundle\Entity\Item", mappedBy="factura", cascade={"persist", "remove"})
*/
private $items;
/**
* Add item
*
* @param \Acme\TestBundle\Entity\Item $item
*
* @return Factura
*/
public function addItem(\Acme\TestBundle\Entity\Item $item)
{
$item->setFactura($this);
$this->items[] = $item;
return $this;
}
En la entidad Item:
// ../src/Acme/TestBundle/Entity/Item.php
//..
/**
* @var Factura
*
* @ORM\ManyToOne(targetEntity="Acme\TestBundle\Entity\Items", inversedBy="items")
*/
private $factura;
En el template donde se muestra el formulario (new):
<hr> <div>Items: </div> <ul class="items form-group" data-prototype="{{ form_widget(form.items.vars.prototype)|e('html_attr') }}"> <li class="list-group-item"> {{ form_errors(form.items) }} {{ form_widget(form.items) }} </li> </ul> <hr>
En el template donde se muestra el formulario (new):
(Las clases CSS aplicadas a los tags HTML, puede que no sean de bootstrap y se pueden eliminar)
<script>
$(document).ready(function () {
var addLink = $('<a href="#" class="right btn btn-link btn-icon add-icon">Agregar</a>');
var newLinkLi = $('<li class="add-icon-li"></li>').append(addLink);
var collectionHolder = $('ul.items');
collectionHolder.append(newLinkLi);
collectionHolder.data('index', collectionHolder.find(':input').length);
addLink.on('click', function (e) {
e.preventDefault();
addTagForm(collectionHolder, newLinkLi);
});
//Agrego link para borrar
collectionHolder.find('li').each(function () {
if (!$(this).hasClass('add-icon-li')) {
addTagFormDeleteLink($(this));
}
});
function addTagForm(collectionHolder, newLinkLi) {
var prototype = collectionHolder.data('prototype');
var index = collectionHolder.data('index');
var newForm = prototype.replace(/__name__/g, index);
collectionHolder.data('index', index + 1);
var newFormLi = $('<li class="list-group-item"></li>').append(newForm);
newLinkLi.before(newFormLi);
addTagFormDeleteLink(newFormLi);
}
function addTagFormDeleteLink(tagFormLi) {
var removeFormA = $('<a href="#" class="btn btn-link btn-icon delete-icon">Borrar</a>');
tagFormLi.append(removeFormA);
removeFormA.on('click', function (e) {
e.preventDefault();
if (collectionHolder.find(':input').length > 2) {
tagFormLi.remove();
}
});
}
});
</script>