我有发票表和invoice_item表。每个发票都有很多invoiceItem。
创建发票时,会向用户显示包含发票表单字段的表单以及包含invoiceItem表单字段的行。
我想要的是拥有一个“添加新项目”链接,动态地(jQuery,AJAX)添加项目字段的新行。用户应该能够根据需要添加任意数量的行,并且每个新行应该显示在最后一行的下方。
当然,行字段属性也必须正确,以便可以使用saveAll方法轻松插入数据。
使用CakePHP实现这一目标的最佳和最正确的方法是什么?我正在使用CakePHP 2.4.7。
答案 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,例如为GradeSubject
和Grade.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事件的输入
我认为这会有所帮助