Home > Blockchain >  Create elements by looping a javascript object
Create elements by looping a javascript object

Time:10-06

Lets say we have an array of objects and we loop through it and create a div in every iteration.

How could we take the property ol (which is also an array of objects) in every iteration and create an <ol> inside the div for every object in it, with as many <li>'s as the number in the property li. Also, text inside the li should be the text of the property title so it should look like this:

enter image description here

I'm hitting my head to solve it but my noobness doesn't let me. I tried another loop of the ol object inside the outer loop, but I cant get it right.

var array_of_objects = [{
  "name": "john",
  "job": "pilot",
  "email": "[email protected]",
  "ol": [{
    "li": 6,
    "title": "6 li's"
  }, {
    "li": 2,
    "title": "2 li's"
  }, {
    "li": 5,
    "title": "5 li's"
  }]
}, {
  "name": "mark",
  "job": "engineer",
  "email": "[email protected]",
  "ol": [{
    "li": 2,
    "title": "2 li's"
  }, {
    "li": 7,
    "title": "7 li's"
  }, {
    "li": 2,
    "title": "2 li's"
  }, {
    "li": 1,
    "title": "1 li's"
  }]
}, {
  "name": "george",
  "job": "chef",
  "email": "[email protected]",
  "ol": [{
    "li": 1,
    "title": "1 li's"
  }, {
    "li": 3,
    "title": "3 li's"
  }, {
    "li": 4,
    "title": "4 li's"
  }, {
    "li": 3,
    "title": "3 li's"
  }, {
    "li": 3,
    "title": "3 li's"
  }]
}]

function iterate(arr) {
  arr.forEach(i => {
    var name = i.name;
    var job = i.job;
    var email = i.email;
    var ol_li = i.ol_li;
    var str = `<div>
    <span>${name}</span>
    <span>${job}</span>
    <span>${email}</span>
    <span>ol's should be placed here</span>
    </div>`
    $("body").append(str);
  })
}

iterate(array_of_objects)
div {
  display: flex;
  flex-direction: column;
  border: thin solid black;
  margin: 0.4em;
  padding: 0.2em;
}

span:not(:nth-child(4)) {
  display: flex;
  flex-direction: column;
  border: thin solid red;
  margin: 0.2em;
  padding: 0.2em;
}

span:nth-child(4) {
  display: flex;
  flex-direction: row;
  margin: 0.4em;
  padding: 0.2em;
}

ol {
  border: thin solid blue;
  margin: 0.2em;
}

li {
  margin: 0.2em;
}
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>

CodePudding user response:

I think this should do the trick :

  • Map throw ol array and put single li item in a variable;
  • Use repeat() function to print it in ol variable

var array_of_objects = [
  {
    "name":"john",
    "job":"pilot",
    "email":"[email protected]",
    "ol":[
      {"li":6,"title":"6 li's"},
      {"li":2,"title":"2 li's"},
      {"li":5,"title":"5 li's"}
    ]
  },
  {
    "name":"mark",
    "job":"engineer",
    "email":"[email protected]",
    "ol":[
      {"li":2,"title":"2 li's"},
      {"li":7,"title":"7 li's"},
      {"li":2,"title":"2 li's"},
      {"li":1,"title":"1 li's"}
    ]
  },
  {
    "name":"george",
    "job":"chef",
    "email":"[email protected]",
    "ol":[
      {"li":1,"title":"1 li's"},
      {"li":3,"title":"3 li's"},
      {"li":4,"title":"4 li's"},
      {"li":3,"title":"3 li's"},
      {"li":3,"title":"3 li's"}
    ]
  }
]

  function iterate(arr){

  arr.forEach(i => {

  var name = i.name;
  var job = i.job;
  var email = i.email;
  var ol_li = i.ol;
  var list = "";
  var ol = ol_li.forEach(o=>{
     l = `<li>${o.title}</li>`
     list = `${list} <ol> ${l.repeat(o.li)} </ol>`

  })
  var str = `<div>
  <span>${name}</span>
  <span>${job}</span>
  <span>${email}</span>
  <span>${list}</ol>
  </div>`

  $("body").append(str);

  })

  }

  iterate(array_of_objects)
div{
  display:flex;
  flex-direction:column;
  border:thin solid black;
  margin:0.4em;
  padding:0.2em;
}
span:not(:nth-child(4)){
  display:flex;
  flex-direction:column;
  border:thin solid red;
  margin:0.2em;
  padding:0.2em;
}
span:nth-child(4){
  display:flex;
  flex-direction:row;
  margin:0.4em;
  padding:0.2em;
}
ol{
  border:thin solid blue;
  margin:0.2em;
}
li{
  margin:0.2em;
}
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>
</head>
<body>
</body>
</html>

CodePudding user response:

To do what you require you can use map() to loop through the ol array of each object and create a HTML string which can be appended to the div you create.

Note the use of fill() in the example below to create the required number of li elements with the same content.

Also note that the same approach can be used to both tidy the code and improve performance as it means you only append to the DOM once when the loop completes, instead of within each loop iteration.

Try this:

var array_of_objects = [{name:"john",job:"pilot",email:"[email protected]",ol:[{li:6,title:"6 li's"},{li:2,title:"2 li's"},{li:5,title:"5 li's"}]},{name:"mark",job:"engineer",email:"[email protected]",ol:[{li:2,title:"2 li's"},{li:7,title:"7 li's"},{li:2,title:"2 li's"},{li:1,title:"1 li's"}]},{name:"george",job:"chef",email:"[email protected]",ol:[{li:1,title:"1 li's"},{li:3,title:"3 li's"},{li:4,title:"4 li's"},{li:3,title:"3 li's"},{li:3,title:"3 li's"}]}];

function htmlFromData(arr) {
  return arr.map(obj => {
    let olHtml = obj.ol.map(ol => `<ol>${(new Array(ol.li)).fill(`<li>${ol.title}</li>`).join('')}</ol>`).join('');
    return `<div>
      <span>${obj.name}</span>
      <span>${obj.job}</span>
      <span>${obj.email}</span>
      <span>${olHtml}</span>
    </div>`    
  }).join('');
}

$("body").append(htmlFromData(array_of_objects));
div {
  display: flex;
  flex-direction: column;
  border: thin solid black;
  margin: 0.4em;
  padding: 0.2em;
}

span:not(:nth-child(4)) {
  display: flex;
  flex-direction: column;
  border: thin solid red;
  margin: 0.2em;
  padding: 0.2em;
}

span:nth-child(4) {
  display: flex;
  flex-direction: row;
  margin: 0.4em;
  padding: 0.2em;
}

ol {
  border: thin solid blue;
  margin: 0.2em;
}

li {
  margin: 0.2em;
}
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>

  • Related