[英]How can I perform dynamic operations on dynamically added elements?
My objective: 我的目标:
The relevant code: 相关代码:
The table I want to populate: 我要填充的表格:
<table id='performer-payments' class='performer-profile payments-table'>
<tr>
<th> Period </th>
<th> Amount </th>
<th> Paid? </th>
</tr>
</table>
The code that populates the table: 填充表格的代码:
for (period in data['Performers'][performer]['Payments']) {
var amount = utils.calcPerformerCut(data, performer, period);
var row = "<tr>";
row += "<td> " + period + " </td>";
row += "<td> " + amount + " $ </td>";
row += "<td>";
row += "<div class='performer-profile payment-status'>";
row += data['Performers'][performer]['Payments'][period];
row += "</div>";
row += "<select id='payment-status-" + performer + "-" + period + "' class='perfomer-profile hidden-onload displayNone payment-status-menu'>";
row += "<option value='paid'>Paid</option>";
row += "<option value='unpaid'>Unpaid</option>";
row += "<option value='transfer'>Transfer to...</option>";
row += "</select>";
row += "<select id='payment-transfer-period-" + performer + "-" + period + "' class='performer-profile hidden-onload displayNone payment-period-menu'>";
for (var i=0; i < data['Periods'].length; i++) {
row += "<option value='" + period + "'>" + period + '</option>';
}
row += "</select>";
row += "</td>";
row += "</tr>";
$('#performer-payments').append(row);
$('#performer-payments').on('change', {perf: performer, per: period}, function (even) {
if (even.target.value == 'transfer') {
utils.toggleVisible($('#payment-transfer-period-' + even.data.perf + '-' + even.data.per), true);
} else {
utils.toggleVisible($('#payment-transfer-period-' + even.data.perf + '-' + even.data.per), false);
}
});
}
For reference, the code that toggles visibility: 供参考,切换可见性的代码:
exports.toggleVisible = function (selector, visible) {
if (visible) {
selector.removeClass('displayNone').addClass('displayBlock');
} else {
selector.removeClass('displayBlock').addClass('displayNone');
}
}
There are (at least) two issues with this: 这个(至少)有两个问题:
Note: I welcome feedback on this in general - I am an experienced programmer but have very little experience with HTML/JS/Jquery. 注意:我欢迎对此提出反馈 - 我是一名经验丰富的程序员,但对HTML / JS / Jquery的经验很少。 Further, I have decided to not use templates for this project since I am trying to learn the basics, so if you get pancreatitis from seeing the way I am 'dynamically' adding the rows to the table, I apologize but it is partly intentional.
此外,我决定不使用模板进行这个项目,因为我正在尝试学习基础知识,所以如果你从看到我动态'添加行到表的方式得到胰腺炎,我道歉,但它是部分故意的。
Other than that, please ask for clarifications if something is not clear here. 除此之外,如果此处不清楚,请询问澄清。
Edit : Here is the relevant part of the data structure: 编辑 :这是数据结构的相关部分:
data = {
'Performers': {
'Dira Klaggen': {
'Payments': {
'Q1': 'Paid',
'Q2': 'Paid',
'Q3': 'Unpaid'
},
},
'Holden Bolden': {
'Payments': {
'Q2': 'Transferred to Q3',
'Q3': 'Unpaid'
}
},
'Manny Joe': {
'Payments': {
'Q1': 'Paid',
'Q2': 'Unpaid',
'Q3': 'Unpaid',
}
}
},
'Periods': [
'Q1',
'Q2',
'Q3'
]
}
You do not attach the change
handler to the right element. 您没有将
change
处理程序附加到右侧元素。 I should be the first select
in the row... Instead of the whole table
. 我应该是行中的第一个
select
...而不是整个table
。
Try this change
handler: 试试这个
change
处理程序
$('#performer-payments').find('#payment-status-' + performer + '-' + period).on('change', function(){
if ($(this).val() == 'transfer') {
$(this).next('select').show();
} else {
$(this).next('select').hide();
}
});
id
for the first select
.
select
的“复杂”唯一id
来简化它。
Say you use the class
"payment-status": 假设你使用的
class
“支付状态”:
The handler would be: 处理程序将是:
$('#performer-payments').on('change', '.payment-status', function(){ if ($(this).val() == 'transfer') { $(this).next('select').show(); } else { $(this).next('select').hide(); } });
And this handler can be out of the row appending loop because it uses delegation . 并且此处理程序可以不在行追加循环中,因为它使用委托 。
Let's clean up your code by doing the following things: 让我们通过执行以下操作来清理代码:
Use classes instead of ugly IDs. 使用类而不是丑陋的ID。
Use data-attributes or hidden input fields to hold extra information. 使用数据属性或隐藏的输入字段来保存额外信息。
Use event delegation to bind dynamically-created elements. 使用事件委派来绑定动态创建的元素。 Inside the event handler, use tree traversal methods to limit the scope of the search based on the current element
this
. 在事件处理器,使用树遍历方法来限制基于当前元素的搜索范围
this
。
Let's apply these things. 让我们应用这些东西。
Build each row like this. 像这样构建每一行。
{PLACEHOLDER}
is where you put your variable stuff like you have in your code. {PLACEHOLDER}
是您在代码中放置变量的地方。
<tr>
<td>{PERIOD}</td>
<td>{AMOUNT} $ </td>
<td>
<div class='performer-profile payment-status'>
{SOMETHING-RELATING-TO-PERFORMER-PAYMENT-PERIOD}
</div>
<!-- remove ID -->
<!-- store performer and period in data-attributes -->
<select class='perfomer-profile hidden-onload displayNone payment-status-menu' data-performer='{PERFORMER}' data-period='{PERIOD}'>
<option value='paid'>Paid</option>
<option value='unpaid'>Unpaid</option>
<option value='transfer'>Transfer to...</option>
</select>
<!-- remove ID -->
<select class='performer-profile hidden-onload displayNone payment-period-menu'>
<option value='{PERIOD}'>{PERIOD}</option>
<option value='{PERIOD}'>{PERIOD}</option>
<option value='{PERIOD}'>{PERIOD}</option>
<!-- etc -->
</select>
</td>
</tr>
In your JavaScript, create a delegated event handler . 在JavaScript中,创建委派的事件处理程序 。 Note the syntax.
请注意语法。
$(function () {
// ...
for (period in data['Performers'][performer]['Payments']) {
// build and append row
}
// create delegated event handler once and outside FOR loop
$(document).on('change', '.payment-status-menu', function () {
// get the current status menu
var statusMenu = $(this);
// find its related period menu
var periodMenu = statusMenu.closest('tr').find('.payment-period-menu');
// toggle its visibility
periodMenu.toggle(this.value == 'Transfer');
// of course, this could be a one-liner
//$(this).closest('tr').find('.payment-period-menu').toggle(this.value == 'Transfer');
});
});
It doesn't seem like you need (2.) but if you do, within the event handler, use statusMenu.data('performer')
or statusMenu.data('period')
to get its performer and period values. 看起来你不需要(2.)但是如果你这样做,在事件处理程序中,使用
statusMenu.data('performer')
或statusMenu.data('period')
来获取它的执行者和周期值。 You could also do this.dataset.performer
or this.dataset.period
. 您也可以执行
this.dataset.performer
或this.dataset.period
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.