2

I have added a dynamic buttons inside for loop on webpage using JavaScript and assigned a unique id to each button. I wants to assign onclick() event Listener to each button but this function is not being assigned to any of dynamic buttons. Kindly help me resolving this. Thank You.

myfunction()is working but myfunction1() has some problem. I cannot see onclick event in its dynamically HTML. HTML view

There are JS file. data.js contains arrays of objects and other contains function which access the data.

// function.js
function chargerArticles() {

  var myShoppingCart = [];



  var articles = document.getElementById("content");
  for (var i = 0; i < catalogArray.length; i++) {


    //Product div
    var article = document.createElement("div");
    article.setAttribute("class", "aa");
    //Unique id
    article.id = i + "-article";

      //Product Name
    var articleName = document.createElement("h4");
    articleName.setAttribute("class", "aa-product-title");
    var articleNameLink=  document.createElement('a');
    articleNameLink.setAttribute('href',"#");
    articleNameLink.innerText = catalogArray[i].name;
    articleName.appendChild(articleNameLink);

    article.appendChild(articleName);

    //Command Input Area
    var zoneCmd = document.createElement("div");

    var inputCmd = document.createElement("input");

    //Button of add to cart
    var button = document.createElement("BUTTON");
    button.setAttribute("class", "Btn hvr-underline-btn");
    button.innerHTML = " ADD";

    //Button unique id
    button.id = i + "-cmd";

    //not working
    button.addEventListener("click", myFunction1);

    function myFunction1() {
      var item = this.getAttribute("id");
      var pos = item.substring(0, 1);
      document.getElementById("1235").innerHTML = "Hello World";
      addToCart(pos);
    }

    //working
    document.getElementById("1234").addEventListener("click", myFunction);

    function myFunction() {
      document.getElementById("1234").innerHTML = "YOU CLICKED ME!";
    }


    zoneCmd.appendChild(button); //child 2
    //zoneCmd child of article element
    article.appendChild(zoneCmd);



    //finally article as a child of articles 
    articles.appendChild(article);
  }
}

function searchInCart(name) //T-Shirt
{
  myShoppingCart = myCartArray;
  var name1 = name;
  var stop = 0;
  for (var i = 0; i < myShoppingCart.length && stop == 0; i++) {
    if (myShoppingCart[i].name == name1) {
      stop = 1;
      // console.log("Hello wooooorld!");
      return true;
    } else {
      return false;
    }
  }

}

function addToCart(pos) {

  if (searchInCart(catalogArray[pos].name)) {
    alert("Already Exist!"); // display string message

  } else {
    var ident = pos + "-qte";
    var quatity = document.getElementById("ident").value;
    if (quatity > 0) {
      var articleCmd = {}; //array of  objects
      articleCmd.name = catalogArray[pos].name;
      articleCmd.price = catalogArray[pos].price;
      articleCmd.qte = quatity;
      articleCmd.priceTotal = articleCmd.price * articleCmd.qte;
      myCartArray.push(articleCmd);

    } else {
      // alert
    }
  }

}


//data.js

// data.js
var catalogArray = [{
    code: 100,
    name: "T Shirt c100",
    desc: "Lorem ipsum, or lipsum as it is sometimes known as",
    price: 150,
    image: "./images/img100.jpg"
  },
  {
    code: 101,
    name: "T Shirt c101",
    desc: "Lorem ipsum, or lipsum as it is sometimes known as",
    price: 250,
    image: "./images/img101.jpg"
  },

];



var myCartArray = [{
    name: "T Shirt c100",
    price: 150,
    qte: 2,
    TotalPrice: 150,
  }

];
2
  • WHY do you have the function INSIDE the loop. That is very very inefficient. Also delegate instead Commented Jun 11, 2020 at 6:30
  • you might need to add event delegations to the dynamically added elements. Commented Jun 11, 2020 at 6:36

2 Answers 2

2

This issue occurred because you defined myfunction1 dynamically. In other words, this element wasn't defined during the initial rendering of the page.

You can fix it by using event delegation. Here is how:

Instead of defining the callback on the element, define it for all children of the PARENT element that have the matching css class. For example:

     $( ".btnContainer .btn" ).on( "click", function( event ) {
        event.preventDefault();
     console.log("clicked");

    });

where:

 <div class='btnContainer'>
 </div>

Now when you add buttons with (class name btn) dynamically as children of btnContainer, they will still get access to the click handler, because the event handler isn't bound to the element btn, but to it's parent, hence when the click event is fired, the parent delegates the event to all it's children with the matching class(es)!

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you. I get your point but can you help fixing this in my code using delegation. I am v beginner to JS so I am not getting where and to add it in my code as I have someother data to display in page I skipped in question. I am updating it for your reference
1
  1. Do not add a function in a loop
  2. Delegate

Have a look here. There are MANY issues, I have addressed a few of them

You MAY want to do

button.setAttribute("data-code",item.code);

instead of

button.id = i + "-cmd";
// function.js

const content = document.getElementById("content");

content.addEventListener("click",function(e) {
  const tgt = e.target,  // the element clicked
    id = tgt.id; // the ID of the element
  if (id.indexOf("-cmd") !=-1) { // is that element one of our buttons?
   // get the name of the article from the button - this could also be a data attibute
    var pos = id.split("-")[1]; 
    addToCart(pos);
  }  
})

function chargerArticles() {

  const myShoppingCart = catalogArray.map(function(item, i) {
    //Product div
    var article = document.createElement("div");
    article.setAttribute("class", "aa");
    //Unique id
    article.id = i + "-article";
    // here would be a good place to add item.name or something
    //Command Input Area
    var zoneCmd = document.createElement("div");
    var inputCmd = document.createElement("input");
    //Button of add to cart
    var button = document.createElement("BUTTON");
    button.setAttribute("class", "Btn hvr-underline-btn");
    button.innerHTML = " ADD";
    //Button unique id
    button.id = i + "-cmd";

    zoneCmd.appendChild(button); //child 2
    //zoneCmd child of article element
    article.appendChild(zoneCmd);
    //finally article as a child of articles 
    articles.appendChild(article);
    content.appendChild(articles) // ???
  })
}

function searchInCart(name) {
  return myCartArray.filter(function(x) {
    return x.name === name
  })[0];
}

5 Comments

Thank you very much. I appreciate your efforts for helping me out. can you please explain const tgt = e.target, id = tgt.id; I am beginner in JS and I don't have thorough understanding of code.
when you delegate - like I delegate from content, the (e) is the event passed. The event.target is the button or whatever else is clicked in the content container. I get the ID from the target to test if it is one that contains the -cmd your buttons contain.
what am I supposed to write dynamic button's id in place of e.target?
No. The tgt = e.target gets what was clicked. Then I test tgt.id to see if it contains ".....-cmd"
PS: Using just the index as an article ID is possibly not very scalable - perhaps use the code

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.