简体   繁体   中英

How to add .data attribute to dynamically created elements

I'm creating dynamically elements from $.get request, to each of created elements i have to add a data attribute with an object from that request.

So let's assume i have the following $.get request:

    $('.loader').show();
      $.get(api)
        .done(function (data) {

          let plu = [];
          data.map(d => {
            if (d.codplu == "COPERTI" || d.desc == "") return false;

            plu.push('<div class="card card-product" data-toggle="modal" data-target="#modalProduct" data-plu="' + d.id + '">')
            if (d.img) {
              plu.push('<img class="img-fluid" src="data:image/png;base64,' + d.img + '">')
            } else {
              plu.push('<img class="img-fluid d-none" src="">')
            }

            plu.push('<div class="card-body">')
            plu.push('<div class="row">')
            plu.push('<div class="col">')
            plu.push('<h5 class="card-title mb-0">' + d.desc + '</h5>')
            plu.push('</div>')
            plu.push('<div class="col-auto">')
            plu.push('<h5 class="text-right text-success price">' + formatPrezzo(d.prezzo) + '</h5>')
            plu.push('</div>')
            plu.push('</div>')
            plu.push('<p class="card-tag mb-0">')
            d.attributi.map(attr => {
              plu.push('<span class="badge badge-success mr-1" style="background-color: ' + toColor(attr.background) + '; color: ' + toColor(attr.text) + ';">' + attr.desc + '</span>')
            })
            plu.push('</p>')
            plu.push('<p class="card-text text-muted">' + d.estesa + '</p>')
            if (profilo.moduli.ordine_menu && profilo.tavolo != "0") {
              plu.push('<a href="#" class="btn btn-outline-primary btn-block add-cart cd-add-to-cart js-cd-add-to-cart" data-price="' + d.prezzo.toFixed(2) + '">' + AddToCartText() + '</a>') // BUTTON CREATED HERE
            }
            plu.push('</div>')
            plu.push('</div>')
          })
          $('#' + menu + '-tab > .card-columns').append(plu.join(""));
          $('.loader').fadeOut("slow");
        })

To each button created in each elements i have to add a .data attribute but how could i do it without iterating again through each button and by checking it's id to set the right .data attribute?

As you use jQuery, use it to the full, and create all elements using the appropriate jQuery methods. This has as additional advantage that you avoid potential character escaping issues, and avoid accidental mistakes in opening/closing tags.

So here is how your code could be converted to more jQuery style. It is then also a breeze to call .data at the appropriate place:

$('.loader').show();
$.get(api).done(function (data) {
    $('#' + menu + '-tab > .card-columns').append(
        data.map(d => d.codplu == "COPERTI" || d.desc == "" ? ""
            : $("<div>", { 
                "class": "card card-product",
                "data-toggle": "modal",
                "data-target": "#modalProduct",
                "data-plu": d.id
            }).append($("<img>", {
                    "class": "img-fluid" + (d.img ? "" : " d-none"),
                    src: d.img ? "data:image/png;base64," + d.img : "",
                }),
                $("<div>").addClass("card-body").append(
                    $("<div>").addClass("row").append(
                        $("<div>").addClass("col").append(
                            $("<h5>").addClass("card-title mb-0").text(d.desc)
                        ),
                        $("<div>").addClass("col-auto").append(
                            $("<h5>").addClass("text-right text-success price").text(formatPrezzo(d.prezzo))
                        )
                    ),
                    $("<p>").addClass("card-tag mb-0").append(
                        d.attributi.map(attr =>
                            $("<span>").addClass("badge badge-success mr-1").css({ 
                                backgroundColor: toColor(attr.background),
                                color: toColor(attr.text)
                            }).text(attr.desc)
                        )
                    ),
                    $("<p>").addClass("card-text text-muted").text(d.estesa),
                    profilo.moduli.ordine_menu && profilo.tavolo != "0" 
                        ? $("<a>", { 
                            href: "#",
                            "class": "btn btn-outline-primary btn-block add-cart cd-add-to-cart js-cd-add-to-cart",
                            "data-price": d.prezzo.toFixed(2)
                        }).text(AddToCartText()).data(d.varianti)
                        : ""
                )
            )
        )
    )
    $('.loader').fadeOut("slow");
});

The newly added elements are being added as raw HTML so, in order to call a jQuery method on them, you'd need to rewrite your code so every element comes from a variable.

An alternative is to find the new elements starting from the jQuery object you already have (as long as you have something that identifies them):

 const menu = "foo"; let plu = []; plu.push("<div>One</div>"); plu.push("<div>Two</div>"); $('#' + menu + '-tab >.card-columns').append(plu.join("")).find("div:nth-child(1)").css({color: "green"}).data("data1", "value1").end().find("div:nth-child(2)").css({color: "blue"}).data("data2", "value2").end();
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div id="foo-tab"> <div class="card-columns">Your items here:</div> </div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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