0

I am trying to create a list dynamically via javascript by clicking a button. This list is created properly. Each item of this list has an onclick function with a different argument. So, by clicking on each item, an other word("Saab" or "Volvo" or "BMW") is printed on the screen. The problem is that by clicking on every item of the list, only the last word("BMW") is printed.

This is my html and javascript code.

function myfunction1() {
  var i;
  var cars = ["Saab", "Volvo", "BMW"];
  for (i = 0; i < cars.length; i = i + 1) {
    var y = cars[i];
    var mycar = cars[i];
    var li = document.createElement('li');
    var a = document.createElement('a');
    a.innerHTML = y;
    a.onclick = function() {
      showcar(mycar);
    }
    li.appendChild(a);
    document.getElementById("allcars").appendChild(li);
  }
}

function showcar(car) {
  document.getElementById("demo").innerHTML = car;
}
<button onclick="myfunction1()">Perla</button>
<ul>
 <p id="allcars"></p>
</ul>    
<p id="demo"></p>

If I click on Saab or Volvo or BMW only BMW will be printed on the screen. What I want is: when I click on Saab item of the list, "Saab" is printed. When I click on Volvo item, "Volvo" is printed. When I click on "BMW" item, "BMW" is printed.

4 Answers 4

3

You can wrap the code in another closure that will then run immediately:

function myfunction1(){
    var cars = ["Saab", "Volvo", "BMW"];
    for (var i = 0; i < cars.length; i=i+1) {
        (function (i) {
            var cars = ["Saab", "Volvo", "BMW"];
            var y = cars[i];
            var mycar = cars[i];
            var li = document.createElement('li');
            var a = document.createElement('a');
            a.innerHTML = y;
            a.onclick = function(){
                showcar(mycar);
            };
            li.appendChild(a);
            document.getElementById("allcars").appendChild(li);
        }).call(this, i);
    }
} 

function showcar(car){
    document.getElementById("demo").innerHTML = car;
}
Sign up to request clarification or add additional context in comments.

4 Comments

My bad, i was checked with something different
@PredatorIWD why edit your first answer? it is now much more complicated..
@ShadowFiend I just added the showcar function on the first solution. And added the second one with let, I didn't change the first ones code.
@ShadowFiend Oh well, I just wanted to give another solution since the first one requires one array to be declared twice.
1

function myfunction1() {
  var i;
  var cars = ["Saab", "Volvo", "BMW"];
  for (i = 0; i < cars.length; i = i + 1) {
    var y = cars[i];
    var mycar = cars[i];
    var li = document.createElement('li');
    var a = document.createElement('a');
    a.innerHTML = y;
    a.onclick = function() {
      showcar(this);
    }
    li.appendChild(a);
    document.getElementById("allcars").appendChild(li);
  }
}

function showcar(obj) {
  document.getElementById("demo").innerHTML = obj.innerHTML;
}
<button onclick="myfunction1()">Perla</button>
<ul>
 <p id="allcars"></p>
</ul>    
<p id="demo"></p>

Its printing BMW only because your mycar variable having that value in every last iteration. you just send that clicked object and print that innerHTML value.

Comments

1

I've made a couple of changes to your solution:

  • I've bound a single event listener to the ul element for click events. This way you don't have to add a click event on every li.
  • Use an a when you want to navigate, in almost all other cases where you need an interactive element use a button.

const
  carList = document.getElementById('car-list'),
  createTrigger = document.getElementById('create-car-list'),
  demoElement = document.getElementById('demo');
  
function onCarListClicked(event) {
  const
    carMake = event.target.getAttribute('data-car-make');
  
  demoElement.textContent = carMake;
}
  
function onCreateCarList(){
  const
    cars = ["Saab", "Volvo", "BMW"];
    
  cars.forEach(car => {
      const 
        li = document.createElement('li'),
        button = document.createElement('button');  
      button.setAttribute('type', 'button');
      button.setAttribute('data-car-make', car);
      button.textContent = car;
      
      li.appendChild(button);
      carList.appendChild(li);
  });
}

carList.addEventListener('click', onCarListClicked);
createTrigger.addEventListener('click', onCreateCarList);
<button id="create-car-list">Perla</button>
<ul id="car-list">
    <p id="allcars"></p>
</ul>    
<p id="demo"></p>

Comments

0

Problem raises because of mycar variable changes on every iteration and element's onclick function uses the last one.

You can use this function for example:

a.onclick = function () {
    showcar(this.innerHTML);
}

this keyword is referring the element which is clicked. So it's working as expected.

Comments

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.