skip to Main Content

I have an HTML page that gathers data from a database and uses that data to produce dynamic HTML elements. The problem is that these elements have to create a button that submits data without refreshing the page and then call a function productList(formId);.

This is the current function:

function getWidgets(){
    
    var listUrl = base_url + widgetsPath + url_auth;
    
    console.log("Sending GET to " + listUrl);
    
    function getSuccess(obj){
        var dataWidget = obj.data;

        for (let i=0; i< dataWidget.length; i++){

            var id = dataWidget[i].id;
            var description = dataWidget[i].description;
            var price = dataWidget[i].pence_price;
            var url = dataWidget[i].url;
            var index = i;
            
            
            console.log("index: ",i);
            console.log(dataWidget[i].id);
            console.log(dataWidget[i].description);
            console.log(dataWidget[i].pence_price);
            console.log(dataWidget[i].url);
            console.log(" ");

            var template =`<!-- product -->
            <div class="container" class="product" id="productId_${index}">
                <form action="" class="product">
                    <img src="${url}"></img>
                    <p class="product_Description">${description}</p>
                    <input type="hidden" class="productId" value=${id}>
                    <input type="hidden" class="price" value="0.${price}">
                    <label for="quantity">Quantity:</label>
                    <input type="number" class="quantity" value="1" min="1">
                    <button class="submit">Add to cart</button>
                </form>
            </div>
            <script>
                        document.addEventListener("DOMContentLoaded",() =>{
                            const product${index} = document.querySelector("#productId_${index}")
                            product1.addEventListener("submit",e=>{
                                e.preventDefault();
                                var formId = "productId_${index}";
                                productList(formId);
                            });
                        });
            </script>
            <!-- END product -->`

            $("#widgetContainer").append(template);

        }
        console.log("success");
        console.log(dataWidget);
        
    };
    
    $.ajax(listUrl, {type: "GET", data: {},success: getSuccess });
};

getWidgets();

2

Answers


  1. You do not need to dynamically add a <script> block for each widget you append to your page. Instead, you can add a single submit event handler that will be able to handle the submit event for all of the <form> elements you add dynamically. The code would look like the following:

    $('#widgetContainer').on('submit', 'form.product', function (e) {
      e.preventDefault();
      const formId = $(this).parent().attr('id');
      productList(formId);
    });
    

    The above code is using Event Delegation to handle the submit event for any <form> element with a class of "product". In the handler, we get the id attribute of the <form> element’s parent.

    Here is a fiddle for reference.

    Login or Signup to reply.
  2. Under the hood, jQuery’s append() parses the HTML-string by using Element.innerHTML.

    As mentioned in MDN’s section Security considerations for innerHTML:

    … HTML specifies that a <script> tag inserted with innerHTML should not execute.

    So instead of executing the code by appending a <script> tag, simply execute it:

    var template = /*without script tag*/;
    
    $("#widgetContainer").append(template);
    
    // Script tag's code
    document.addEventListener("DOMContentLoaded",() => {
      const product = document.querySelector("#productId_${index}")
      product.addEventListener("submit", e => {
        e.preventDefault();
        var formId = "productId_${index}";
        productList(formId);
      });
    });
    

    Or better, use event delegation as 76484’s answer shows. That way you wouldn’t have to add individual listeners.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search