简体   繁体   English

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

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

My objective: 我的目标:

  • Filling in the 'performer-payments' table dynamically with JS/Jquery 使用JS / Jquery动态填写'performer-payments'表
  • For each (dynamically added) row in the table, one of the data cells contains a dropdown box. 对于表中的每个(动态添加的)行,其中一个数据单元格包含一个下拉框。
  • This dropdown box should, when a certain option is selected, make visible another dropdown box (in the same cell). 当选择某个选项时,此下拉框应该显示另一个下拉框(在同一个单元格中)。 Otherwise, this second dropdown should be invisible. 否则,第二个下拉列表应该是不可见的。
  • Elsewhere I am accomplishing the hide/show dynamics by means of a toggleVisible function, which simply adds custom classes which is marked by css to hide or show the element. 在其他地方,我通过toggleVisible函数完成隐藏/显示动态,它只是添加了由css标记的自定义类来隐藏或显示元素。

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: 这个(至少)有两个问题:

  • The #payment-transfer-period-... select box is never displayed, even when the 'transfer' option is chosen in the first select box. 即使在第一个选择框中选择了“转移”选项,也不会显示#payment-transfer-period -...选择框。 From debugging efforts it seems to me that it could be that the #payment-transfer-period-.. for some reason is not a valid object yet, or something like that. 从调试工作来看,在我看来,#payment-transfer-period- ..由于某种原因可能还不是一个有效的对象,或类似的东西。
  • (Obviously, really), the on-change event is triggered N times (N=number of periods) because I am just telling the program to trigger whenever something in the table changes. (显然,真的),on-change事件被触发N次(N =周期数),因为我只是告诉程序在表中的某些内容发生变化时触发。 I would like it to trigger only for the relevant dropdown, but when I tried adding the #payment-status-... as a selector to the .on() function, it made it never trigger. 我希望它只触发相关的下拉列表,但当我尝试将#payment-status -...作为选择器添加到.on()函数时,它使它永远不会触发。

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


Second approach: 第二种方法:
You could simplify that by using a class instead of a "complicated" unique 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: 让我们通过执行以下操作来清理代码:

  1. Use classes instead of ugly IDs. 使用类而不是丑陋的ID。

  2. Use data-attributes or hidden input fields to hold extra information. 使用数据属性或隐藏的输入字段来保存额外信息。

  3. 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.performerthis.dataset.period

暂无
暂无

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

相关问题 如何通过jquery访问视图中动态添加的元素 - How can I access dynamically added elements in views via jquery 如何将事件处理程序添加到Google日历页面上动态添加的元素? - How can I add event handlers to dynamically added elements on a Google Calendar page? 标准事件如何在动态添加的元素上触发? (JQuery的) - How can standard events fire on dynamically added elements? (JQuery) 如何使JS应用于动态添加的DOM元素? - How do I make JS apply to dynamically added DOM elements? 如何将点击事件添加到JQuery中动态添加的元素? - How do I add click events to dynamically added elements in JQuery? 如何为 HTML 中动态添加的元素添加索引? - How do I add index to dynamically added elements in HTML? 我如何在JavaScript中执行操作就像在Java流中进行操作管道一样? - How can I perform operations in JavaScript just like we do pipeline of operations in Java streams? 如何获取不同选项卡的实例,以便可以存储变量/执行特定于各个选项卡的操作 - How can I get instances of different tabs such that I can store variables / perform operations specific to respective tabs 如何使用JavaScript动态获取输入值并执行算术运算 - How to get an input value dynamically and perform arithmetic operations using javascript Mongo陷阱上的异步操作:如何执行同步,我有正确的逻辑 - Asynchronous operations on Mongo trap: how can I perform kind of synchronously, I have correct logic
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM