Shamppi Shamppi - 7 months ago 11
HTML Question

JS or jQuery way to dynamically create DOM elements

Could anyone point me a more easy-to-read-and-expand way of doing this:

data = {/*very very long json*/};
var inHTML = "";

jQuery.each(data, function(key, value){
var articleUrl = 'url-to-somewhere';

var newItem = "<div class='item'><div class='item--poster'><img src='"+data[key].backdropUrl+"' alt='title'/></div><div class='item--content'><h2>"+data[key].title+"</h2><ul><li>"+data[key].productionYear+"</li><li>"+data[key].productionCountry+"</li></ul></div><div class='item--link'><p><a class='' href='"+articleUrl+"'>Lue lisää</a></p></div></div>";
inHTML += newItem;

});

jQuery("#container").html(inHTML);


What I'm looking for is something similar to ng-repeat of Angular.

Answer

I would bet on using placeholder template and .clone(). What exactly you need to do is, create a Master DOM like this:

<div id="master-dom" class="item">
  <p><strong>Name</strong> <span class="Name"></span></p>
  <p><strong>Age</strong> <span class="Age"></span></p>
</div>

Now give a CSS that would hide the Master DOM:

#master-dom {display: none;}

The next attempt would be, have a #content area:

<div id="content"></div>

And now comes the JavaScript part.

var data = [
  {
    "name": "Praveen",
    "age": 27
  },
  {
    "name": "Jon Skeet",
    "age": 29
  },
  {
    "name": "Kumar",
    "age": 25
  }
];

Having the above as the data structure, you can loop through and insert:

$.each(data, function (i, v) {
  // We need the v.
  $("#master-dom").clone()
                  .removeAttr("id")
                  .find(".Name").text(v.name).end()
                  .find(".Age").text(v.age).end()
                  .appendTo("#content");
});

See the final output here:

$(function() {
  var data = [{
    "name": "Praveen",
    "age": 27
  }, {
    "name": "Jon Skeet",
    "age": 29
  }, {
    "name": "Kumar",
    "age": 25
  }];

  $.each(data, function(i, v) {
    // We need the v.
    $("#master-dom").clone()
      .removeAttr("id")
      .find(".Name").text(v.name).end()
      .find(".Age").text(v.age).end()
      .appendTo("#content");
  });
});
* {
  margin: 0;
  padding: 0;
  list-style: none;
}
#master-dom {
  display: none;
}
.item p strong {
  display: inline-block;
  width: 75px;
}
<script src="https://code.jquery.com/jquery-2.1.4.js"></script>
<div id="master-dom" class="item">
  <p><strong>Name</strong> <span class="Name"></span></p>
  <p><strong>Age</strong> <span class="Age"></span></p>
</div>
<div id="content"></div>

I really believe this would be the underlying logic behind Angular's ng-repeat. Also I would use this above logic if I were in your place.

Comments