What I'm trying to do is "Embed a Collection of Forms" as described here : http://symfony.com/doc/2.3/cookbook/form/form_collections.html
I have managed to get it set up correctly and up to the stage where I add JavaScript/JQuery it works fine. However now I have added the JQuery section I can't get it to work quite right.
Initial Loaded Form
Form after clicking add product once.
As you can see above when I click add product it is adding 2 sets of the add product form. This in it's self is not right. To make matters worse, the first of the 2 new rows added doesn't persist to the database. The same thing happens each time I 'add new product'.
Now the documentation only deals with one filed 'tags' but I assumed just adapting the tutorial to my needs would be enough. I have fiddled everywhere inside my Entities/Mappings/Controllers and Views trying to sort this. Think I have tinkered with everything trying to get it right but cannot. Except for the JQuery code itself as I have no idea about JQuery or Javascript (Having enough of a job learning PHP at the moment without complicating things though I fully intend on learning it as soon as I've got a grasp of Symfony).
//Recipe Form
class RecipeType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('recipename') ->add('recipedesc')
->add('recipeyeild') ->add('recipecost');
$builder->add('product', 'collection', array(
'type' => new ProductRecipeType(),
'allow_add' => true,
'by_reference' => false,
'allow_delete' => true,));
}
//ProductRecipe Form
class ProductRecipeType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('amount') ->add('product');
}
//Recipe view new.twig
<h1>Recipes creation</h1>
{{ form_start(form) }}
{{ form_row(form.recipename) }} {{ form_row(form.recipedesc) }}
{{ form_row(form.recipeyeild) }} {{ form_row(form.recipecost) }}
<h3>Products</h3>
<ul class="product" data-prototype="{{ form_widget(form.product.vars.prototype)|e }}">
{% for products in form.product %}
{{ form_row(products.amount) }}
{{ form_row(products.product) }}
{% endfor %}
</ul>
{{ form_end(form) }}
//JQuery for the recipe form (Currently in the Twig file however I do intent on moving it to a separate file once working properly)
<script>
var $collectionHolder;
// setup an "add a product" link
var $addProductsLink = $('<a href="#" class="add_product_link">Add a product</a>');
var $newLinkLi = $('<li></li>').append($addProductsLink);
jQuery(document).ready(function() {
// Get the ul that holds the collection of tags
$collectionHolder = $('ul.product');
// add a delete link to all of the existing tag form li elements
$collectionHolder.find('li').each(function() {
addProductsFormDeleteLink($(this));
});
// add the "add a tag" anchor and li to the tags ul
$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);
$addProductsLink.on('click', function(e) {
// prevent the link from creating a "#" on the URL
e.preventDefault();
// add a new tag form (see next code block)
addProductsForm($collectionHolder, $newLinkLi);
});
});
function addProductsForm($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(/__product__/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);
addProductsFormDeleteLink($newFormLi);
}
function addProductsFormDeleteLink($productsFormLi) {
var $removeFormA = $('<a href="#">Delete</a>');
$productsFormLi.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
$productsFormLi.remove();
});
}
Now what I think is causing the issue is this line :
$collectionHolder.data('index', $collectionHolder.find(':input').length);
Specifically the .find(':input') section as I'm guessing it is counting the input fields but this is just pure guess work.
Also while I'm asking this question I also would prefer it if the 'Add products' link didn't have a delete button as when clicked it completely removes the 'Add products' link from the form, and the only way to get it back is by refreshing the page. Think I've covered everything.
EDIT
This is the prototype stuff created from 'view source' (Which looks disgusting to be honest lol)
<ul class="product" data-prototype="<div
id="bc_inventorybundle_recipe_product___name__"><div><
label for="bc_inventorybundle_recipe_product___name___amount"
class="required">Amount</label><input type="
text" id="bc_inventorybundle_recipe_product___name___amount"
name="bc_inventorybundle_recipe[product][__name__][amount]"
required="required" /></div><div><label
for="bc_inventorybundle_recipe_product___name___product">Product<
/label><select id="bc_inventorybundle_recipe_product___name___product"
name="bc_inventorybundle_recipe[product][__name__][product]"><option
value=""></option><option
value="66">Butter</option><option
value="67">Beef</option><option
value="68">Jam</option><option value="69">Xanthan
Gum</option><option value="70">Test
Product</option><option
value="71">test</option><option
value="72">test</option><option
value="73">Beef</option><option
value="74">Beef</option></select></div></div>">
