简体   繁体   English

按类名选择动态添加的元素

[英]Selecting dynamically added elements by class name

I have am HTML code which for simplicity looks like this:我有 HTML 代码,为简单起见,如下所示:

<div class="main-container">
    <div class="group-area group1" id="group1">
        <select class="slct" id="slct1">
            <option>Group A</option>
            <option>Group B</option>
            <option>Group C</option>
        </select>
        <div class="participant-area">
            <!-- empty, can be filled with "<div class='participant'></div>" elements -->
        </div>
    </div>
    <button class="add-group">Show another group</button>
</div>

In the above inteface, the user can select the name of the group from the select drop down, and the the participants of that group will be shown in the 'participant-area'.在上面的界面中,用户可以从选择下拉列表中选择组的名称,该组的参与者将显示在“参与者区域”中。 They will be drawn from a presaved list, and will be added using jQuery append:它们将从预先保存的列表中提取,并将使用 jQuery append 添加:

<script>
    $(document).on('change', '.slct', function() {
                var number = $(this).attr("id").charAt(4); //gets the number '1' from the id name
                var key = $(this).find("option:selected").val(); //gets the value to be used later
                var constructedClass = ".group" + number; //result: "group1" 
                presavedList.forEach(participant => {
                        $(constructedClass + " .participant-area") //selecting participant area that is inside group1
                            .append($("<div>").addClass("participant")
                                .append($("<h2>").text(participant.name))
                            );
                    }


                })

</script>

However, user can also click on the 'add-group' button at the end of the main container, and have another area just like the first one displayed, that can be used to see participants of a different group.但是,用户也可以单击主容器末尾的“添加组”按钮,并显示另一个区域,就像显示的第一个区域一样,可用于查看不同组的参与者。 But this time, the classes will be group2 instead of group1, slct2 instead of slct1, and so on.但是这一次,类将是 group2 而不是 group1,slct2 而不是 slct1,依此类推。 This is done by having a global variable that is incremented whenever the button is clicked:这是通过具有一个在单击按钮时递增的全局变量来完成的:

<script>
    var areaNumber = 1;
   $(".add-group").click(function () {
       areaNumber++;

       $(".main-container")
           .append($("<div>").addClass( "group"+areaNumber).addClass("group-area").attr("id", "group"+ areaNumber)
                   .append($("<select>")) //etc... Reconstruct the same one as original
                    .append($("<div>"))   //etc... Reconstruct the same one as original                    
   });
</script>

My problem is related selecting the groupN class of the dynamically created elements (like group2, group3, etc).我的问题与选择动态创建的元素(如 group2、group3 等)的 groupN 类有关。 In the first function above - after a second area has been created and its select value changed - the change is being detected normally and the $(document).on('change', '.slct', function() {...}) is being fired normally.在上面的第一个函数中 - 在创建第二个区域并更改其选择值之后 - 正常检测到更改并且 $(document).on('change', '.slct', function() {... }) 被正常解雇。 However, the 5th line in that function:但是,该函数中的第 5 行:

$(constructedClass + " .participant-area").append(//etc)

is not working: the constructedClass is not being detected by the function, even though it exists in the time of firing it - but I believe it's not being detected because it was not present at the time of initial parsing of javascript.不工作:constructedClass 没有被函数检测到,即使它在触发它时存在 - 但我相信它没有被检测到,因为它在最初解析 javascript 时不存在。 Is that correct?那是对的吗? Is there any way to solve this?有没有办法解决这个问题? (Be able to select dynamically generated elements by their uniquely generated class names?). (能够通过它们唯一生成的类名来选择动态生成的元素?)。

Thank you for reading this far and for any help you can offer.感谢您阅读本文并提供任何帮助。

Do not use incremental id and class attributes .不要使用增量idclass属性 It is an anti-pattern.这是一种反模式。 It makes your code needlessly complex, more verbose, and difficult to maintain.它使您的代码变得不必要地复杂、冗长且难以维护。

A much better solution is to group common elements by behaviour using a single class attribute.更好的解决方案是使用单个class属性按行为对公共元素进行分组。 That way you can use DOM traversal to relate them to each other.这样你就可以使用 DOM 遍历将它们相互关联起来。 It also allows you to clone() content (as it's all identical) without the need to spaghetti-fy your JS by filling it with HTML.它还允许您clone()内容(因为它们都是相同的),而无需通过用 HTML 填充它来对您的 JS 进行意大利面化。

With that said, try this:话虽如此,试试这个:

 let presavedList = [{ name: 'Foo bar' }, { name: 'Lorem ipsum' }] $(document).on('change', '.slct', function() { var html = presavedList.map(item => `<div class="participant"><h2>${item.name}</h2></div>`); $(this).next('.participant-area').html(html); }); $(".add-group").click(function() { var $clone = $('.group:first').clone(); $clone.find('select').val(''); $clone.find('.participant-area').empty(); $clone.appendTo('.main-container'); });
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div class="main-container"> <div class="group-area group"> <select class="slct"> <option value="">Please select...</option> <option>Group A</option> <option>Group B</option> <option>Group C</option> </select> <div class="participant-area"></div> </div> <button class="add-group">Show another group</button> </div>

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

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