嵌入式表单多个字段-Symfony2 JQuery多个字段 [英] Embedded Forms Multiple Fields - Symfony2 JQuery multiple fields

查看:59
本文介绍了嵌入式表单多个字段-Symfony2 JQuery多个字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要执行的操作是嵌入表格的集合",如此处所述:

现在,文档仅处理一个归档的标签",但我认为仅根据我的需要对教程进行调整就足够了.我在实体/映射/控制器和视图中到处摆弄各种东西,试图对此进行排序.认为我已经尽一切努力使它正确,但是不能.除了JQuery代码本身之外,我对JQuery或Javascript也不了解(目前我有足够的工作来学习PHP,而不会使事情变得复杂,尽管我完全打算在掌握Symfony之后立即学习它)./p>

//食谱表格

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表格

class ProductRecipeType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
->add('amount') ->add('product');
}

//配方视图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查询配方表单(当前在Twig文件中,但是我打算在工作正常后将其移至单独的文件中)

<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();
    });
}

现在我认为导致此问题的是此行:

$collectionHolder.data('index', $collectionHolder.find(':input').length);

特别是.find(':input')部分,因为我猜它正在对输入字段进行计数,但这只是纯粹的猜测工作.

当我问这个问题时,如果添加产品"链接没有删除按钮,我也希望使用它,因为单击它会从表单中完全删除添加产品"链接,这是唯一的方法取回页面是通过刷新页面.认为我已经涵盖了所有内容.

编辑

这是从查看源代码"创建的原型内容(老实说,这看上去真令人恶心)

     <ul class="product" data-prototype="&lt;div
 id=&quot;bc_inventorybundle_recipe_product___name__&quot;&gt;&lt;div&gt;&lt;
 label for=&quot;bc_inventorybundle_recipe_product___name___amount&quot;
 class=&quot;required&quot;&gt;Amount&lt;/label&gt;&lt;input type=&quot;
 text&quot; id=&quot;bc_inventorybundle_recipe_product___name___amount&quot;
 name=&quot;bc_inventorybundle_recipe[product][__name__][amount]&quot; 
 required=&quot;required&quot; /&gt;&lt;/div&gt;&lt;div&gt;&lt;label
 for=&quot;bc_inventorybundle_recipe_product___name___product&quot;&gt;Product&lt;
 /label&gt;&lt;select id=&quot;bc_inventorybundle_recipe_product___name___product&quot;
 name=&quot;bc_inventorybundle_recipe[product][__name__][product]&quot;&gt;&lt;option  
 value=&quot;&quot;&gt;&lt;/option&gt;&lt;option 
 value=&quot;66&quot;&gt;Butter&lt;/option&gt;&lt;option 
 value=&quot;67&quot;&gt;Beef&lt;/option&gt;&lt;option 
 value=&quot;68&quot;&gt;Jam&lt;/option&gt;&lt;option value=&quot;69&quot;&gt;Xanthan
 Gum&lt;/option&gt;&lt;option value=&quot;70&quot;&gt;Test
 Product&lt;/option&gt;&lt;option
 value=&quot;71&quot;&gt;test&lt;/option&gt;&lt;option 
 value=&quot;72&quot;&gt;test&lt;/option&gt;&lt;option 
 value=&quot;73&quot;&gt;Beef&lt;/option&gt;&lt;option  
 value=&quot;74&quot;&gt;Beef&lt;/option&gt;&lt;/select&gt;&lt;/div&gt;&lt;/div&gt;"> 

解决方案

好吧,所以我认为我已经破解了很多.

问题1: 添加产品按钮会生成3个表单",但是只有2个会保留.

答案1: 添加< li>标记表单中的所有行.

 {% for products in form.product %}
   <li>{{ form_row(products.amount) }}</li>
   <li>{{ form_row(products.product) }}</li>
 {% endfor %}

这可以解决持久性问题,但是...

问题2: 我最初删除<的原因. li>标签是因为它将在所有内容中添加删除"按钮...

答案2: 我通过在<中添加一个类来解决此问题. li>一个字段.

  <li class="formrowprod">{{ form_row(products.product) }}</li>

,然后通过在JQuery中对其进行修改来选择它:

$collectionHolder.find('li').each(function()

对此:

$collectionHolder.find('li.formrowprod').each(function()

问题3: 现在几乎所有内容都已修复,除了"DeleteDelete"之外其他所有内容(在开始行上彼此相邻的两个删除"按钮既丑陋又不必要)(每个配方都至少有一种产品,所以没人会想要删除所有产品)

答案3:

取下锂.完全来自.find():

    $collectionHolder.find('formrowprod').each(function() {
    addProductsFormDeleteLink($(this));
    });


所以现在一切正常,但是当我单击添加产品"时,它仍然加载2行而不是1行,但这不是世界末日,但我想知道为什么有人可以提供帮助.

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="&lt;div
 id=&quot;bc_inventorybundle_recipe_product___name__&quot;&gt;&lt;div&gt;&lt;
 label for=&quot;bc_inventorybundle_recipe_product___name___amount&quot;
 class=&quot;required&quot;&gt;Amount&lt;/label&gt;&lt;input type=&quot;
 text&quot; id=&quot;bc_inventorybundle_recipe_product___name___amount&quot;
 name=&quot;bc_inventorybundle_recipe[product][__name__][amount]&quot; 
 required=&quot;required&quot; /&gt;&lt;/div&gt;&lt;div&gt;&lt;label
 for=&quot;bc_inventorybundle_recipe_product___name___product&quot;&gt;Product&lt;
 /label&gt;&lt;select id=&quot;bc_inventorybundle_recipe_product___name___product&quot;
 name=&quot;bc_inventorybundle_recipe[product][__name__][product]&quot;&gt;&lt;option  
 value=&quot;&quot;&gt;&lt;/option&gt;&lt;option 
 value=&quot;66&quot;&gt;Butter&lt;/option&gt;&lt;option 
 value=&quot;67&quot;&gt;Beef&lt;/option&gt;&lt;option 
 value=&quot;68&quot;&gt;Jam&lt;/option&gt;&lt;option value=&quot;69&quot;&gt;Xanthan
 Gum&lt;/option&gt;&lt;option value=&quot;70&quot;&gt;Test
 Product&lt;/option&gt;&lt;option
 value=&quot;71&quot;&gt;test&lt;/option&gt;&lt;option 
 value=&quot;72&quot;&gt;test&lt;/option&gt;&lt;option 
 value=&quot;73&quot;&gt;Beef&lt;/option&gt;&lt;option  
 value=&quot;74&quot;&gt;Beef&lt;/option&gt;&lt;/select&gt;&lt;/div&gt;&lt;/div&gt;"> 

解决方案

Ok then, so I think I've pretty much cracked it.

Issue 1: Add product button resulted in 3 'forms' however only 2 would be persisted.

Answer 1: Add < li > tags to all rows in form.

 {% for products in form.product %}
   <li>{{ form_row(products.amount) }}</li>
   <li>{{ form_row(products.product) }}</li>
 {% endfor %}

This fixes persistence but...

Issue 2: The reason I had initially removed the < li > tags was because It would add 'Delete' buttons to everything ...

Answer 2: I fixed this by adding a class to the < li > for one field.

  <li class="formrowprod">{{ form_row(products.product) }}</li>

and then selected it by modifying this in the JQuery:

$collectionHolder.find('li').each(function()

To this:

$collectionHolder.find('li.formrowprod').each(function()

Issue 3: Now almost everything is fixed, everything except there is still "DeleteDelete" (Two Delete buttons next to each other on the starting row which is both ugly and unnecessary (Every recipe will have at least one product so no one will want to remove all)

Answer 3:

Remove the li. completely from .find():

    $collectionHolder.find('formrowprod').each(function() {
    addProductsFormDeleteLink($(this));
    });


So it now all works, pretty well however it still loads 2 rows instead of 1 when I click 'Add Product' but it's not the end of the world but would love to know why if anyone can help.

这篇关于嵌入式表单多个字段-Symfony2 JQuery多个字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆