动态添加表单字段行 - cakePHP

时间:2014-04-08 22:23:18

标签: php jquery ajax cakephp cakephp-2.4.7

我有发票表和invoice_item表。每个发票都有很多invoiceItem。

创建发票时,会向用户显示包含发票表单字段的表单以及包含invoiceItem表单字段的行。

我想要的是拥有一个“添加新项目”链接,动态地(jQuery,AJAX)添加项目字段的新行。用户应该能够根据需要添加任意数量的行,并且每个新行应该显示在最后一行的下方。

当然,行字段属性也必须正确,以便可以使用saveAll方法轻松插入数据。

使用CakePHP实现这一目标的最佳和最正确的方法是什么?我正在使用CakePHP 2.4.7。

3 个答案:

答案 0 :(得分:1)

这里是我如何使用包含隐藏ID,标签和输入字段的数据来完成的,所有数据都包含在字段集中。你可以用实际的表来包装它。

这是为两组字段生成的HTML以及单击以添加行的链接:

   <fieldset>
   <input type="hidden" name="data[VmfrDesignatedIncome][0][id]" value="668" id="VmfrDesignatedIncome0Id"/>
   <div class="input text">
   <label for="VmfrDesignatedIncome0Designation">Designation</label>
   <input name="data[VmfrDesignatedIncome][0][designation]" value="blah" maxlength="512" type="text" id="VmfrDesignatedIncome0Designation"/></div>
   </fieldset>

    <fieldset>
    <input type="hidden" name="data[VmfrDesignatedIncome][1][id]" value="669" id="VmfrDesignatedIncome1Id"/>
    <div class="input text">
    <label for="VmfrDesignatedIncome1Designation">Designation</label>  

    <input name="data[VmfrDesignatedIncome][1][designation]" value="blah2" maxlength="512" type="text" id="VmfrDesignatedIncome1Designation"/></div>
    </fieldset>

     <a href="#" id="addrow">Add row</a>

这里是克隆页面上最后一个字段集的Javascript,然后修改id,name和字段值以将其中的数字增加一。请注意,选择器必须使用>子选择器准确选择每个标签或字段。

/* As the strings to the function below may have [ or ]
** we want to stop it being treated as a regexp
*/
RegExp.quote = function(str) {
     return str.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
 };

function findNumberAddOne(attributeString) {
    /*Finds the number in the given string
    ** and returns a string with that number increased by one
    */
    var re = new RegExp("(.*)([0-9])(.*)");
    var nPlusOne = attributeString.replace(re, "$2")+"+1";
    var newstr = attributeString.replace(re, "$1")+eval(nPlusOne)+attributeString.replace(re, "$3");
    return newstr;
}

$(document).ready(function() {
/* Duplicate the last set of designated income fields and increase the relevants id/name etc.
** so that it works as a new row in the table when saved*/
    $('#addrow').click(function() { 
        $('fieldset:last').clone().insertAfter('fieldset:last');
        $('fieldset:last > input').attr('id',findNumberAddOne($('fieldset:last > input').attr('id')));
        $('fieldset:last > input').attr('value',''); /*Blank out the actual value*/
        $('fieldset:last > input').attr('name',findNumberAddOne($('fieldset:last > input').attr('name')));
        $('fieldset:last > div > label').attr('for',findNumberAddOne($('fieldset:last > div > label').attr('for')));
        $('fieldset:last > div > input').attr('id',findNumberAddOne($('fieldset:last > div > input').attr('id')));
        $('fieldset:last > div > input').attr('value',''); /*Blank out the actual value*/
        $('fieldset:last > div > input').attr('name',findNumberAddOne($('fieldset:last > div > input').attr('name')));
    });
});

答案 1 :(得分:0)

请查看Dynamic form input fields in CakePHP教程。我对CakePHP 2.x以及CakePHP 3.x使用了相同的内容。本教程中的一个问题是动态字段ID创建。每次为相同的动态字段创建相同的ID,例如为GradeSubjectGrade.0.subject字段创建Grade.1.subject。如果您需要每个字段的动态ID,您可以修改本教程,如下所示。

根据教程,只需将View/Elements/grades.ctp内容更改为:

<?php
    $key = isset($key) ? $key : '{{ key }}';
    // I changed <%= key %> to {{ key }}
?>
<tr>
    <td>
        <?php echo $this->Form->hidden("Grade.{$key}.id") ?>
        <?php echo $this->Form->text("Grade.{$key}.subject",array("id"=>"Grade{$key}Subject")); ?>
    </td>   
    <td>
        <?php echo $this->Form->select("Grade.{$key}.grade", array(
            'A+',
            'A',
            'B+',
            'B',
            'C+',
            'C',
            'D',
            'E',
            'F'
        ), array(
            'empty' => '-- Select grade --',
            "id"=>"Grade{$key}Grade"
        )); ?>
    </td>
    <td class="actions">
        <a href="#" class="remove">Remove grade</a>
    </td>
</tr>

并将您的add.ctp javascript代码更改为:

<script>
    $(document).ready(function() {
        //I changed undescore default template settings
        _.templateSettings = {
          interpolate: /\{\{(.+?)\}\}/g
        }

        var
            gradeTable = $('#grade-table'),
            gradeBody = gradeTable.find('tbody'),
            gradeTemplate = _.template($('#grade-template').remove().text()),
            numberRows = gradeTable.find('tbody > tr').length;

        gradeTable
            .on('click', 'a.add', function(e) {
                e.preventDefault();

                $(gradeTemplate({key: numberRows++}))
                    .hide()
                    .appendTo(gradeBody)
                    .fadeIn('fast');
            })
            .on('click', 'a.remove', function(e) {
                    e.preventDefault();

                $(this)
                    .closest('tr')
                    .fadeOut('fast', function() {
                        $(this).remove();
                    });
            });

            if (numberRows === 0) {
                gradeTable.find('a.add').click();
            }
    });
</script>

答案 2 :(得分:-1)

我心中最简单的想法

1-使用名称数组(<input type="text" name="items[]"/>

输入您的项目

2-创建一个带有课程&#34; addmore&#34;

的按钮

3-使用jquery clone复制该按钮上的click事件的输入

我认为这会有所帮助