最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

json - Using Javascript loop to create multiple HTML elements - Stack Overflow

programmeradmin1浏览0评论

I would like to use a javascript loop to create multiple HTML wrapper elements and insert JSON response API data into some of the elements (image, title, url, etc...).

Is this something I need to go line-by-line with?

<a class="scoreboard-video-outer-link" href="">
  <div class="scoreboard-video--wrapper">
    <div class="scoreboard-video--thumbnail">
      <img src="">
    </div>
    <div class="scoreboard-video--info">
      <div class="scoreboard-video--title">Pelicans @ Bulls Postgame: E'Twaun Moore 10-8-17</div>
    </div>
  </div>
</a>

What I am trying:

var link = document.createElement('a');
document.getElementsByTagName("a")[0].setAttribute("class", "scoreboard-video-outer-link");
document.getElementsByTagName("a")[0].setAttribute("url", "google"); 
mainWrapper.appendChild(link);

var videoWrapper= document.createElement('div');
document.getElementsByTagName("div")[0].setAttribute("class", "scoreboard-video-outer-link");
link.appendChild(videoWrapper);

var videoThumbnailWrapper = document.createElement('div');
document.getElementsByTagName("div")[0].setAttribute("class", "scoreboard-video--thumbnail");
 videoWrapper.appendChild(videoThumbnailWrapper);

var videoImage = document.createElement('img');
document.getElementsByTagName("img")[0].setAttribute("src", "url-of-image-from-api");
videoThumbnailWrapper.appendChild(videoImage);

Then I basically repeat that process for all nested HTML elements.

  • Create A-tag
  • Create class and href attributes for A-tag
  • Append class name and url to attributes
  • Append A-tag to main wrapper

  • Create DIV

  • Create class attributes for DIV
  • Append DIV to newly appended A-tag

I'd greatly appreciate it if you could enlighten me on the best way to do what I'm trying to explain here? Seems like it would get very messy.

I would like to use a javascript loop to create multiple HTML wrapper elements and insert JSON response API data into some of the elements (image, title, url, etc...).

Is this something I need to go line-by-line with?

<a class="scoreboard-video-outer-link" href="">
  <div class="scoreboard-video--wrapper">
    <div class="scoreboard-video--thumbnail">
      <img src="http://via.placeholder./350x150">
    </div>
    <div class="scoreboard-video--info">
      <div class="scoreboard-video--title">Pelicans @ Bulls Postgame: E'Twaun Moore 10-8-17</div>
    </div>
  </div>
</a>

What I am trying:

var link = document.createElement('a');
document.getElementsByTagName("a")[0].setAttribute("class", "scoreboard-video-outer-link");
document.getElementsByTagName("a")[0].setAttribute("url", "google."); 
mainWrapper.appendChild(link);

var videoWrapper= document.createElement('div');
document.getElementsByTagName("div")[0].setAttribute("class", "scoreboard-video-outer-link");
link.appendChild(videoWrapper);

var videoThumbnailWrapper = document.createElement('div');
document.getElementsByTagName("div")[0].setAttribute("class", "scoreboard-video--thumbnail");
 videoWrapper.appendChild(videoThumbnailWrapper);

var videoImage = document.createElement('img');
document.getElementsByTagName("img")[0].setAttribute("src", "url-of-image-from-api");
videoThumbnailWrapper.appendChild(videoImage);

Then I basically repeat that process for all nested HTML elements.

  • Create A-tag
  • Create class and href attributes for A-tag
  • Append class name and url to attributes
  • Append A-tag to main wrapper

  • Create DIV

  • Create class attributes for DIV
  • Append DIV to newly appended A-tag

I'd greatly appreciate it if you could enlighten me on the best way to do what I'm trying to explain here? Seems like it would get very messy.

Share Improve this question edited Oct 13, 2017 at 22:00 4ndy asked Oct 13, 2017 at 21:34 4ndy4ndy 4588 silver badges27 bronze badges 8
  • 3 What have you tried so far and what part of the above are you having problems with? – NewToJS Commented Oct 13, 2017 at 21:39
  • I am in the process of doing what I have described above. For instance: var link = document.createElement('a'); document.getElementsByTagName("a")[0].setAttribute("class", "scoreboard-video-outer-link"); document.getElementsByTagName("a")[0].setAttribute("url", "google."); mainWrapper.appendChild(link); Then I basically repeat that process for all nested HTML elements. – 4ndy Commented Oct 13, 2017 at 21:43
  • Templating HTML like this is a very mon problem. So mon, in fact, there are many JavaScript frameworks that can do it. I'd remend you look into a framework like React, Vue, or Angular. – Sidney Commented Oct 13, 2017 at 21:45
  • Thanks Sidney. I'll look into those frameworks more. I have used VUE before to create sites but never to create loops like this. This will eventually live on a Drupal page so I'll have to explore that marriage more closely as well. – 4ndy Commented Oct 13, 2017 at 21:50
  • @4ndy Please edit/update your question and include what you have tried. Thank you. – NewToJS Commented Oct 13, 2017 at 21:51
 |  Show 3 more ments

3 Answers 3

Reset to default 4

Here's my answer. It's notated. In order to see the effects in the snippet you'll have to go into your developers console to either inspect the wrapper element or look at your developers console log.

We basically create some helper methods to easily create elements and append them to the DOM - it's really not as hard as it seems. This should also leave you in an easy place to append JSON retrieved Objects as properties to your elements!

Here's a Basic Version to give you the gist of what's happening and how to use it

//create element function

function create(tagName, props) {
  return Object.assign(document.createElement(tagName), (props || {}));
}

//append child function

function ac(p, c) {
  if (c) p.appendChild(c);
  return p;
}

//example: 
//get wrapper div
let mainWrapper = document.getElementById("mainWrapper");

//create link and div
let link = create("a", { href:"google." });
let div = create("div", { id: "myDiv" });

//add link as a child to div, add the result to mainWrapper
ac(mainWrapper, ac(div, link));

//create element function

function create(tagName, props) {
  return Object.assign(document.createElement(tagName), (props || {}));
}

//append child function

function ac(p, c) {
  if (c) p.appendChild(c);
  return p;
}

//example: 
//get wrapper div
let mainWrapper = document.getElementById("mainWrapper");

//create link and div
let link = create("a", { href:"google.", textContent: "this text is a Link in the div" });
let div = create("div", { id: "myDiv", textContent: "this text is in the div! " });

//add link as a child to div, add the result to mainWrapper
ac(mainWrapper, ac(div, link));
div {
border: 3px solid black;
padding: 5px;

}
<div id="mainWrapper"></div>

Here is how to do specifically what you asked with more thoroughly notated code.

//get main wrapper
let mainWrapper = document.getElementById("mainWrapper");

//make a function to easily create elements
//function takes a tagName and an optional object for property values
//using Object.assign we can make tailored elements quickly.

function create(tagName, props) {
  return Object.assign(document.createElement(tagName), (props || {}));
}


//document.appendChild is great except 
//it doesn't offer easy stackability
//The reason for this is that it always returns the appended child element
//we create a function that appends from Parent to Child 
//and returns the piled element(The Parent).
//Since we are ALWAYS returning the parent(regardles of if the child is specified) 
//we can recursively call this function to great effect
//(you'll see this further down)
function ac(p, c) {
  if (c) p.appendChild(c);
  return p;
}

//these are the elements you wanted to append
//notice how easy it is to make them!

//FYI when adding classes directly to an HTMLElement
//the property to assign a value to is className  -- NOT class
//this is a mon mistake, so no big deal!

var link = create("a", {
  className: "scoreboard-video-outer-link",
  url: "google."
});

var videoWrapper = create("div", {
  className: "scoreboard-video-outer-link"
});

var videoThumbnailWrapper = create("div", {
  className: "scoreboard-video--thumbnail"
});

var videoImage = create("img", {
  src: "url-of-image-from-api"
});

//here's where the recursion es in:
ac(mainWrapper, ac(link, ac(videoWrapper, ac(videoThumbnailWrapper, videoImage))));

//keep in mind that it might be easiest to read the ac functions backwards
//the logic is this:

//Append videoImage to videoThumbnailWrapper
//Append (videoImage+videoThumbnailWrapper) to videoWrapper 
//Append (videoWrapper+videoImage+videoThumbnailWrapper) to link
//Append (link+videoWrapper+videoImage+videoThumbnailWrapper) to mainWrapper

let mainWrapper = document.getElementById('mainWrapper');

function create(tagName, props) {
  return Object.assign(document.createElement(tagName), (props || {}));
}

function ac(p, c) {
  if (c) p.appendChild(c);
  return p;
}

var link = create("a", {
  className: "scoreboard-video-outer-link",
  url: "google."
});

var videoWrapper = create("div", {
  className: "scoreboard-video-outer-link"
});

var videoThumbnailWrapper = create("div", {
  className: "scoreboard-video--thumbnail"
});



var videoImage = create("img", {
  src: "url-of-image-from-api"
});

ac(mainWrapper, ac(link, ac(videoWrapper, ac(videoThumbnailWrapper, videoImage))));
//pretty fancy.
//This is just to show the output in the log,
//feel free to just open up the developer console and look at the mainWrapper element.

console.dir(mainWrapper);
<div id="mainWrapper"></div>

Short version

Markup.js's loops.

Long version

You will find many solutions that work for this problem. But that may not be the point. The point is: is it right? And you may using the wrong tool for the problem.

I've worked with code that did similar things. I did not write it, but I had to work with it. You'll find that code like that quickly bees very difficult to manage. You may think: "Oh, but I know what it's supposed to do. Once it's done, I won't change it."

Code falls into two categories:

  • Code you stop using and you therefore don't need to change.
  • Code you keep using and therefore that you will need to change.

So, "does it work?" is not the right question. There are many questions, but some of them are: "Will I be able to maintain this? Is it easy to read? If I change one part, does it only change the part I need to change or does it also change something else I don't mean to change?"

What I'm getting at here is that you should use a templating library. There are many for JavaScript.

In general, you should use a whole JavaScript application framework. There are three main ones nowadays:

  • ReactJS
  • Vue.js
  • Angular 2

For the sake of honesty, note I don't follow my own advice and still use Angular. (The original, not Angular 2.) But this is a steep learning curve. There are a lot of libraries that also include templating abilities.

But you've obviously got a whole project already set up and you want to just plug in a template into existing JavaScript code. You probably want a template language that does its thing and stays out of the way. When I started, I wanted that too. I used Markup.js . It's small, it's simple and it does what you want in this post.

https://github./adammark/Markup.js/

It's a first step. I think its loops feature are what you need. Start with that and work your way to a full framework in time.

Take a look at this - [underscore._template] It is very tiny, and useful in this situation. (https://www.npmjs./package/underscore.template).

const targetElement = document.querySelector('#target')

// Define your template
const template = UnderscoreTemplate(
'<a class="<%- link.className %>" href="<%- link.url %>">\
  <div class="<%- wrapper.className %>">\
    <div class="<%- thumbnail.className %>">\
      <img src="<%- thumbnail.image %>">\
    </div>\
    <div class="<%- info.className %>">\
      <div class="<%- info.title.className %>"><%- info.title.text %></div>\
    </div>\
  </div>\
</a>');
 
// Define values for template
const obj = {
  link: {
    className: 'scoreboard-video-outer-link',
    url: '#someurl'
  },
  wrapper: {
    className: 'scoreboard-video--wrapper'
  },
  thumbnail: {
    className: 'scoreboard-video--thumbnail',
    image: 'http://via.placeholder./350x150'
  },
  info: {
    className: 'scoreboard-video--info',
    title: {
      className: 'scoreboard-video--title',
      text: 'Pelicans @ Bulls Postgame: E`Twaun Moore 10-8-17'
    }
  }
};

// Build template, and set innerHTML to output element.
targetElement.innerHTML = template(obj)

// And of course you can go into forEach loop here like

const arr = [obj, obj, obj]; // Create array from our object
arr.forEach(item => targetElement.innerHTML += template(item))
<script src="https://unpkg./[email protected]/dist/underscore.template.js"></script>
<div id="target">qq</div>

发布评论

评论列表(0)

  1. 暂无评论