【问题标题】:How can I handle a Symfony form with TWO CollectionType child forms?如何处理带有两个 CollectionType 子表单的 Symfony 表单?
【发布时间】:2016-05-26 11:55:38
【问题描述】:

我一直在关注 Symfony 指南 here,它描述了如何在表单中生成(并刷新到数据库)关联实体的集合。

我已经按照示例进行了操作,它的工作方式与预期完全一样(添加和删除),但是,如果我确实需要它,我有两个关联的实体:

  • 任务-标签
  • 任务-人员

第二部分的prototype 部分很清楚:

<ul class="tags" data-prototype="{{ form_widget(form.tags.vars.prototype)|e }}">
    ...
</ul>

<ul class="persons" data-prototype="{{ form_widget(form.persons.vars.prototype)|e }}">
    ...
</ul>

但是,对于脚本的更改,我不知道该怎么做,因为我对 javascript/jQuery 没有太多经验。我应该创建一个单独的 jQuery(document).ready(function() {} 函数来处理第二个关联实体,还是应该将它集成到这个现有块中?

我仅针对一个关联实体的功能脚本(来自 twig 模板)是:

<script>
    var $addTagsLink = $('<a href="#" class="add_Tags_link">Add a Tag</a>');
    var $newLinkLi = $('<li></li>').append($addTagsLink);
    jQuery(document).ready(function() {
        // Get the ul that holds the collection of tags
        $collectionHolder = $('ul.Tags');
        // add a delete link to all of the existing tag form li elements
        $collectionHolder.find('li').each(function() {
            addTagsFormDeleteLink($(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);
        $addTagsLink.on('click', function(e) {
            // prevent the link from creating a "#" on the URL
            e.preventDefault();
            // add a new tag form (see next code block)
            addTagsForm($collectionHolder, $newLinkLi);
        });
    });
    function addTagsFormDeleteLink($TagFormLi) {
        var $removeFormA = $('<a href="#">delete this Tag</a>');
        $TagFormLi.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
            $TagFormLi.remove();
        });
    }
    function addTagsForm($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);
        // add a delete link to the new form
        addTagsFormDeleteLink($newFormLi);
        $newLinkLi.before($newFormLi);
    }
</script>

【问题讨论】:

    标签: javascript jquery forms symfony


    【解决方案1】:

    您可以通过添加链接文本作为参数来使addTagsFormDeleteLinkaddTagsForm 这两个函数通用。所以你不要复制它们。在这里,我将它们重命名为 addFormDeleteLinkaddForm

    其余代码可以复制,或插入$.each()JQuery iterator。重复代码(对于两个项目,我发现它更简单,即使不那么优雅):

    // "Add a Tag" link
    var $addTagsLink = $('<a href="#" class="add_Tags_link">Add a Tag</a>');
    var $newTagLinkLi = $('<li></li>').append($addTagsLink);
    
    // "Add a Person" link
    var $addPersonsLink = $('<a href="#" class="add_Persons_link">Add a Person</a>');
    var $newPersonLinkLi = $('<li></li>').append($addPersonsLink);
    
    
    jQuery(document).ready(function() {
    
        //-- Tags --
    
        // Get the ul that holds the collection of tags
        $tagsCollectionHolder = $('ul.Tags');
        // add a delete link to all of the existing tag form li elements
        $tagsCollectionHolder.find('li').each(function() {
            addFormDeleteLink($(this), 'delete this Tag');
        });
        // add the "add a tag" anchor and li to the tags ul
        $tagsCollectionHolder.append($newTagLinkLi);
        // count the current form inputs we have (e.g. 2), use that as the new
        // index when inserting a new item (e.g. 2)
        $tagsCollectionHolder.data('index', $tagsCollectionHolder.find(':input').length);
        $addTagsLink.on('click', function(e) {
            // prevent the link from creating a "#" on the URL
            e.preventDefault();
            // add a new tag form (see next code block)
            addForm($tagsCollectionHolder, $newTagLinkLi, 'delete this Tag');
        });
    
        //-- Persons --
    
        $personsCollectionHolder = $('ul.persons');
        $personsCollectionHolder.find('li').each(function() {
            addFormDeleteLink($(this), 'delete this Person');
        });
        $personsCollectionHolder.append($newPersonLinkLi);
        $personsCollectionHolder.data('index', $personsCollectionHolder.find(':input').length);
        $addPersonsLink.on('click', function(e) {
            e.preventDefault();
            addForm($personsCollectionHolder, $newPersonLinkLi, 'delete this Person');
        });
    });
    
    function addFormDeleteLink($formLi, $anchor) {
        var $removeFormA = $('<a href="#">' + $anchor + '</a>');
        $formLi.append($removeFormA);
        $removeFormA.on('click', function(e) {
            // prevent the link from creating a "#" on the URL
            e.preventDefault();
            // remove the li for the form
            $formLi.remove();
        });
    }
    
    function addForm($collectionHolder, $newLinkLi, $deleteText) {
        // 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/person" link li
        var $newFormLi = $('<li></li>').append(newForm);
        // add a delete link to the new form
        addFormDeleteLink($newFormLi, $deleteText);
        $newLinkLi.before($newFormLi);
    }
    

    【讨论】:

      【解决方案2】:

      您可以附加到现有的jQuery(document).ready 并创建您的函数:addPersonsFormDeleteLink、addPersonsForm

      【讨论】:

        猜你喜欢
        • 2022-01-01
        • 2017-01-15
        • 1970-01-01
        • 2016-10-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-30
        相关资源
        最近更新 更多