Ich habe ein Formular Hotel, die einige CollectionType enthalten, die wiederum einige CollectionType enthalten. In dieser Form möchte ich eine übergeordnete Entität hinzuzufügen, die mehrere Kinder enthalten kann, die wiederum mehrere Einheiten enthalten:Verschachtelte CollectionTypes
class HotelType extends AbstractType{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('rooms', CollectionType::class, array(
'entry_type' => RoomType::class,
"label" => "Add rooms",
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
))
class RoomType extends AbstractType{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options){
$builder
->add('pictures', CollectionType::class, array(
'entry_type' => PictureRoomType::class,
"label" => "Add pictures",
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
))
->add('prices', CollectionType::class, array(
'entry_type' => PriceRoomType::class,
"label" => "Add prices",
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
))
;
Hier die Entitäten Beziehung:
class Room {
/**
* @ORM\ManyToOne(targetEntity = "Hotel", inversedBy = "rooms")
* @ORM\JoinColumn(name = "id_hotel", referencedColumnName = "id")
*/
private $hotel;
/**
* @ORM\OneToMany(targetEntity="PictureRoom", mappedBy="room", cascade={"remove", "persist"})
*/
private $pictures;
/**
* @ORM\OneToMany(targetEntity="PriceRoom", mappedBy="room", cascade={"remove", "persist"})
*/
private $prices;
class Hotel {
/**
* @ORM\OneToMany(targetEntity="Room", mappedBy="hotel", cascade={"remove", "persist"})
*/
private $rooms;
Die HotelController:
class HotelController extends Controller{
/**
* Creates a new Hotel entity.
*
* @Route("/new", name="hotel_new")
* @Method({"GET", "POST"})
*/
public function newAction(Request $request)
{
$hotel = new Hotel();
$form = $this->createForm('AppBundle\Form\HotelType', $hotel);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
if ($hotel->getRooms() != null) {
foreach ($hotel->getRooms() as $room) {
if (!empty($room)) {
$room->setHotel($hotel);
if ($room->getPictures() != null) {
foreach ($room->getPictures() as $picture) {
if (!empty($picture)) {
$picture->setRoom($room);
$picture->upload();
}
}
}
if ($room->getPrices() != null) {
foreach ($room->getPrices() as $price) {
if (!empty($price)) {
$price->setRoom($room);
$price->setIdTva($price->getIdTva()->getId());
}
}
}
$room->setIdTva($room->getIdTva()->getTva());
}
}
}
und ich habe eine JS-Datei, die die Felder handhaben anhängen:
$(document).ready(function() {
var fields = $('div[data-prototype]');
var childElementCount = 1;
fields.each(function (index) {
var field = $(this);
var elementCount = 1;
field.parent().append('<a href="#" class="btn btn-primary" id="add-another-' + index + '"><i class="glyphicon glyphicon-plus"></i> Add an element</a>');
var trigger = $("#add-another-" + index);
var childCollections;
trigger.click(function (e) {
var newWidget = field.attr('data-prototype');
newWidget = newWidget.replace(/label__/g, "");
newWidget = newWidget.replace(/col-md-6/g, "col-md-12");
newWidget = newWidget.replace(/__name__/g, elementCount);
e.preventDefault();
elementCount++;
field.parent().append(newWidget);
childCollections = field.parent().find('.collection');
if(childCollections.length == 1){
childCollections.parent().append('<a href="#" class="btn btn-primary" id="add-another-' + index + '-'+ elementCount + '"><i class="glyphicon glyphicon-plus"></i> Add an element</a>');
var childTrigger = $('#add-another-' + index + '-' + elementCount);
childTrigger.click(function (e) {
var newChildWidget = childCollections.find('div[data-prototype]').attr('data-prototype');
//newChildWidget = newChildWidget.replace(/__child__/g, "_" + childElementCount);
console.log(newChildWidget);
e.preventDefault();
childElementCount += 1;
console.log(childElementCount);
childCollections.parent().append(newChildWidget);
});
} else if (childCollections.length > 1) {
childCollections.each(function(childIndex){
var childField = $(this);
childField.parent().append('<a href="#" class="btn btn-primary" id="add-another-' + index + '-'+ elementCount + childIndex + '"><i class="glyphicon glyphicon-plus"></i> Add an element</a>');
var childTrigger = $('#add-another-' + index + '-' + elementCount + childIndex);
childTrigger.click(function (e) {
var newChildWidget = childField.find('div[data-prototype]').attr('data-prototype');
//newChildWidget = newChildWidget.replace(/__child__/g, "_" + childElementCount);
console.log(newChildWidget);
e.preventDefault();
childElementCount+= 1;
console.log(childElementCount);
childField.parent().append(newChildWidget);
});
})
}
});
});
Das Ereignis funktioniert, wenn ich auf "ein Element hinzufügen" klicken, wird der richtige FormType im richtigen div angehängt. Aber wenn ich die Daten übergebe, bleiben die Enkel-Felder, wie PictureRoom oder PricesRoom, nicht in der Datenbank gespeichert. Kann jemand mit solchen verschachtelten CollectionType-Formularen arbeiten?
Vielen Dank für Ihre Hilfe.