问题描述
<html>
<body>
<table>
<tbody class="project_wrapper">
<tr>
<td scope="row">
<select id="test_project" name="test_project[]">
<option selected>Select</option>
<option>10</option>
<option>20</option>
</select>
</td>
<td><input id="test_value" name="test_value[]" type="text" placeholder="Enter value"></td>
<td><div id="test_calc"></div></td>
</tr>
</tbody>
<tbody>
<tr>
<td colspan="3">
<a href="javascript:void(0);" class="add_project" title="Add project">Add another project</a>
</td>
</tr>
</tbody>
</table>
</body>
</html>
您可以在下拉列表中选择一个值,然后在文本字段中输入数字值时,每次键入时,它将显示该值乘以所选值。您还可以单击“添加另一个项目”链接,它将附加/创建另一个下拉列表和文本字段。这已经有效,并且可以通过以下Jquery代码完成:
<script type="text/javascript">
$(document).ready(function(){
var addProject = $('.add_project');
var wrapper = $('.project_wrapper');
var projectHTML = `<tr>
<td scope="row">
<select id="test_project2" name="test_project[]" class="custom-select">
<option selected>Select</option>
<option>10</option>
<option>20</option>
</select>
</td>
<td><input id="test_value2" name="test_value[]" type="text" placeholder="Enter value"></td>
<td><div id="test_calc2"></div></td>
</tr>`;
$(addProject).click(function(){
$(wrapper).append(projectHTML);
});
});
$('#test_value').keyup(function(){
$('#test_calc').text(Math.round($(this).val() * $("#test_project option:selected").val()));
});
问题是我无法使用乘法功能来工作/显示任何新添加的行的结果。在上方可以看到我尝试对test_value2
和test_calc2
的值进行硬编码,然后在下面添加了它:
$('#test_value2').keyup(function(){
$('#test_calc2').text(Math.round($(this).val() * $("#test_project2 option:selected").val()));
});
我希望结果(至少对于一个新的附加行)以与第一行相同的方式出现,但似乎什么也没有发生。我的目标是使结果显示在附加行中,然后找到一种方法,使keyup计算功能适用于任意数量的附加行(而不是硬编码2、3、4等值)。>
我认为,ids
将在行添加时进行动态分配,然后name
将保持不变,以容纳test_array
和{{ 1}},我将通过PHP进行接收和处理。
谢谢!
解决方法
这些ID必须是唯一的,每当您添加另一行时,您都应该重复这些ID。
为了将 this 关键字与.closest()和.find()结合使用,我将其替换为ID,以获取感兴趣的值。
此外,由于您向表中添加了新元素,因此需要delegate事件。
如果更改选择,则不仅需要在输入字段中键入内容,还需要再次计算。
var addProject = $('.add_project');
var wrapper = $('.project_wrapper');
var projectHTML = '<tr>\
<td scope="row">\
<select class="test_project" name="test_project[]" class="custom-select">\
<option selected>Select</option>\
<option>10</option>\
<option>20</option>\
</select>\
</td>\
<td><input class="test_value" name="test_value[]" type="number" placeholder="Enter value"></td>\
<td><div class="test_calc"></div></td>\
</tr>';
$(addProject).click(function () {
$(wrapper).append(projectHTML);
});
$(document).on('input','.test_value',function (e) {
$(this).closest('tr').find('.test_calc').text(Math.round($(this).val() * $(this).closest('tr').find('.test_project option:selected').val() || 0));
});
$(document).on('change','.test_project',function(e) {
$(this).closest('tr').find('.test_value').trigger('input');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tbody class="project_wrapper">
<tr>
<td scope="row">
<select class="test_project" name="test_project[]">
<option selected>Select</option>
<option>10</option>
<option>20</option>
</select>
</td>
<td><input class="test_value" name="test_value[]" type="number" placeholder="Enter value"></td>
<td>
<div class="test_calc"></div>
</td>
</tr>
</tbody>
<tbody>
<tr>
<td colspan="3">
<a href="javascript:void(0);" class="add_project" title="Add project">Add another project</a>
</td>
</tr>
</tbody>
</table>
,
- 从模板行中删除所有ID,使用类或
name=""
作为选择器 - 为您的TBODY分配一个ID,我们将其用作
.on()
事件delegator - 使用
"input"
事件,而不是"keydown"
事件。您还可以复制/粘贴值,记得吗? - 在
"input"
上-使用.closest()
引用父TR,然后下移(使用.find()
)以查找特定于该行的元素 - 使用
parseInt()
或parseFloat()
处理输入字符串。另外请记住,始终回退到一个数字,即:0
以防止出现NaN
结果
jQuery(function($) {
const projectHTML = `<tr>
<td>
<select name="test_project[]" class="custom-select">
<option value="" selected>Select</option>
<option value="10">10</option>
<option value="20">20</option>
</select>
</td>
<td><input name="test_value[]" type="type" placeholder="Enter value"></td>
<td><div class="result"></div></td>
</tr>`;
const $projects = $("#projects"); // assign an ID to your tbody
const $addProject = $('.add_project');
const arrRow = () => $projects.append(projectHTML);
// Create new row on click
$addProject.on("click",arrRow);
// Add the first row
arrRow();
// use a delegator which is not dymanic (the TBODY in this case),// and use delegated events to any ":input" element:
$projects.on("input",":input",function(ev) {
const $tr = $(this).closest("tr");
const $project = $tr.find('[name="test_project[]"]');
const $value = $tr.find('[name="test_value[]"]');
const $result = $tr.find(".result");
const project = parseInt($project.val(),10) || 0;
const value = parseFloat($value.val()) || 0;
const result = project * value;
$result.text(result);
});
});
<table>
<tbody id="projects"></tbody>
<tbody>
<tr>
<td colspan="3">
<a href="javascript:void(0);" class="add_project" title="Add project">Add another project</a>
</td>
</tr>
</tbody>
</table>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>