繁体   English   中英

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

[英]How can I perform dynamic operations on dynamically added elements?

我的目标:

  • 使用JS / Jquery动态填写'performer-payments'表
  • 对于表中的每个(动态添加的)行,其中一个数据单元格包含一个下拉框。
  • 当选择某个选项时,此下拉框应该显示另一个下拉框(在同一个单元格中)。 否则,第二个下拉列表应该是不可见的。
  • 在其他地方,我通过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'
    ]
}  

您没有将change处理程序附加到右侧元素。 我应该是行中的第一个select ...而不是整个table

试试这个change处理程序

$('#performer-payments').find('#payment-status-' + performer + '-' + period).on('change', function(){
  if ($(this).val() == 'transfer') {
    $(this).next('select').show();
  } else {
    $(this).next('select').hide();
  }
});


第二种方法:
您可以通过使用类而不是第一个select的“复杂”唯一id来简化它。

假设你使用的class “支付状态”:

处理程序将是:

 $('#performer-payments').on('change', '.payment-status', function(){ if ($(this).val() == 'transfer') { $(this).next('select').show(); } else { $(this).next('select').hide(); } }); 

并且此处理程序可以不在行追加循环中,因为它使用委托

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

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

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

  3. 使用事件委派来绑定动态创建的元素。 在事件处理器,使用树遍历方法来限制基于当前元素的搜索范围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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM