0

Trying to get value from JSON file and add on click on button depending on the value of the json data

JSON file

{
  "Cars": [
    {
      "desc": "here are the cars",
      "models": [
        { "model": "bmw", "available": false },
        { "model": "mercedes", "available": false },
        { "model": "anything", "available": true },
        { "model": "audi", "available": false }
      ]
    },
    {
      "desc": "another list",
      "models": [
        { "model": "aaa", "available": false },
        { "model": "bbb", "available": false },
        { "model": "ccc", "available": false },
        { "model": "ddd", "available": true }
      ]
    }
  ]
}

Part of javascript code

function appendData(data) {
  var mainContainer = document.getElementById("myData");
  var div = document.createElement("div");

  for (i in data.Cars) {
    for (j in data.Cars[i].models) {
      var btn = document.createElement("button");
      btn.addEventListener("click", function () {
        alert(j);
      });
      btn.innerHTML = data.Cars[i].models[j].model;
      div.appendChild(btn);
      mainContainer.appendChild(div);
    }
  }
}

When the iteration reach btn.addEventListener the j value always 3

I need to add onclick function depends on the j iteration

Mario
  • 4,784
  • 3
  • 34
  • 50
KSKULL
  • 57
  • 5
  • 4
    Some notes: don't use `alert`, it's from days gone by. Just use `console.log`. Also, don't set `innerHTML` if you're setting text. Use `.textContent`, especially with dynamic concent: inner html _will_ run script code etc. and you don't want that. Also, don't use `for...in` with arrays, it doesn't do what you think (it iterates over _all enumerable properties_, not 'all numbered elements"). For normal array iteration, use `array.forEach(...)`. And lastly, JSON is string data. Once you `JSON.parse` it, it is no longer JSON, it's plain JS, so often (and here), "JSON" is not part of the problem. – Mike 'Pomax' Kamermans Jun 11 '20 at 03:13

2 Answers2

0

Use "let" instead of "var" (see the scope differences), and use a buffer variable,like this:

 var data =     { "Cars": 
        [ { "desc": "here are the cars"
          , "models": 
            [ { "model": "bmw",      "available": false } 
            , { "model": "mercedes", "available": false } 
            , { "model": "anything", "available": true  } 
            , { "model": "audi",     "available": false } 
            ] 
          } 
        , { "desc": "another list"
          , "models": 
            [ { "model": "aaa", "available": false } 
            , { "model": "bbb", "available": false } 
            , { "model": "ccc", "available": false } 
            , { "model": "ddd", "available": true  } 
            ] 
          } 
        ] 
      } 


function appendData() {
  var mainContainer = document.getElementById('myData');
  var div = document.createElement('div');
  for (i in data.Cars) {
    for (j in data.Cars[i].models) {
      var btn = document.createElement('button');
      let alerte = j
      btn.addEventListener('click', function () {
        alert(alerte);
      });
      btn.innerHTML = data.Cars[i].models[j].model;
      div.appendChild(btn);
      mainContainer.appendChild(div);
    }
  }
}

appendData()
<div id="myData"></div>

+1 for the remarks of Mike in the comments.

djcaesar9114
  • 1,880
  • 1
  • 21
  • 41
0

If you want to have access to each value that gets bound to j in your loop, declare it with let instead of var.
You can check out this post for a more detailed explanation of the difference: https://wesbos.com/for-of-es6.

Here's a simple demo of let working as expected in a nested loop:

const myArr = [ ['a', 'b', 'c'], ['a','b','c'] ];
function iterateAndLog(arr){
  for(let i in arr){
    for(let j in arr[i]){
      console.log(j);
    }
  }
}
iterateAndLog(myArr);
Cat
  • 4,141
  • 2
  • 10
  • 18