如何对动态添加的元素执行动态操作?

尤里克

我的目标:

  • 使用JS / Jquery动态填写“执行者付款”表
  • 对于表中的每一行(动态添加),数据单元之一包含一个下拉框。
  • 这个下拉框应,当某个选项被选中,使人们看到另一个下拉框(在相同的细胞)。否则,第二个下拉列表应该是不可见的。
  • 在其他地方,我通过toggleVisible函数完成了隐藏/显示动态,该函数仅添加了由css标记的自定义类来隐藏或显示元素。

相关代码:

我要填充的表:

<table id='performer-payments' class='performer-profile payments-table'>              
    <tr>
        <th> Period </th>                                                             
        <th> Amount </th>                                                             
        <th> Paid? </th>                                                              
    </tr>
</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);
        }
    });
}

作为参考,切换可见性的代码:

exports.toggleVisible = function (selector, visible) {
    if (visible) {
        selector.removeClass('displayNone').addClass('displayBlock');
    } else {
        selector.removeClass('displayBlock').addClass('displayNone');
    }
}

至少有两个问题:

  • 即使在第一个选择框中选择了“转帐”选项,也永远不会显示#payment-transfer-period -...选择框。从调试工作看来,由于某种原因,#payment-transfer-period- ..可能不是一个有效的对象,或者类似的东西。
  • (显然,确实),on-change事件被触发了N次(N =周期数),因为我只是告诉程序表中的任何变化时都要触发。我希望它仅针对相关的下拉菜单触发,但是当我尝试将#payment-status -...作为选择器添加到.on()函数时,它从未触发过。

注意:总体而言,我欢迎对此提供反馈-我是一位经验丰富的程序员,但是对HTML / JS / Jquery的经验很少。此外,由于我正在尝试学习基础知识,因此我决定不为该项目使用模板,因此,如果您因看到自己“动态地”将行添加到表中而出现胰腺炎,我深表歉意,但这在一定程度上是故意的。

除此之外,如果这里有不清楚的地方,请要求澄清。

编辑:这是数据结构的相关部分:

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'
    ]
}  
米奇

让我们通过执行以下操作来清理代码:

  1. 使用类而不是丑陋的ID。

  2. 使用数据属性或隐藏的输入字段来保存其他信息。

  3. 使用事件委托来绑定动态创建的元素。在事件处理程序内部,使用树遍历方法来限制基于当前e​​lement的搜索范围this

让我们应用这些东西。

像这样建立每一行。{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>

在您的JavaScript中,创建一个委托事件处理程序注意语法。

$(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');
    });

});

似乎不需要(2.),但如果需要,则在事件处理程序中使用statusMenu.data('performer')statusMenu.data('period')获取其执行者和期间值。你也可以做this.dataset.performerthis.dataset.period

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章