Home > database >  How can I add HTML class when for loop in JavaScript
How can I add HTML class when for loop in JavaScript

Time:09-29

I am trying to add a class when looping through an array, here is my current code:

var users = [{
    name: "Jan",
    id: "1",
    number: "111-111-111"
  },
  {
    name: "Juan",
    id: "2",
    number: "222-222-222"
  },
  {
    name: "Margie",
    id: "3",
    number: "333-333-333"
  },
  {
    name: "Sara",
    id: "4",
    number: "444-444-444"
  },
  {
    name: "Tyrell",
    id: "5",
    number: "555-555-555"
  },
];

var div = "<div>";
for (var i = 0; i < users.length; i  ) {
  div  = "<p>"   users[i].name   "</p>";
  div  = "<p>"   users[i].id   "</p>";
  div  = "<p>"   users[i].number   "</p>";
}
div  = "</div>";
document.getElementById("usersList").innerHTML = div;
<div class="contact-container">
  <div class="navbar">
    <ul>
      <li>
        <img src="https://img.icons8.com/ios-filled/50/000000/contact-card.png" />
      </li>
      <li>
        <a href="#">View</a>
      </li>
      <li>
        <a href="#">Add</a>
      </li>
      ...
    </ul>
  </div>
  <div class="users" id="usersList">

  </div>

Is there any way I can add a class when looping?

CodePudding user response:

Why don't you put a class right there while looping? like this

for (var i = 0; i < users.length; i  ) {
  div  = "<p class='myclass'>"   users[i].name   "</p>";
  div  = "<p class='myclass'>"   users[i].id   "</p>";
  div  = "<p class='myclass'>"   users[i].number   "</p>";
}

CodePudding user response:

Just add it into your HTML

for (var i = 0; i < users.length; i  ) {
  div  = "<p class='user-name'>"   users[i].name   "</p>";
  div  = "<p class='user-id'>"   users[i].id   "</p>";
  div  = "<p class='user-number'>"   users[i].number   "</p>";
}

var users = [{
    name: "Jan",
    id: "1",
    number: "111-111-111"
  },
  {
    name: "Juan",
    id: "2",
    number: "222-222-222"
  },
  {
    name: "Margie",
    id: "3",
    number: "333-333-333"
  },
  {
    name: "Sara",
    id: "4",
    number: "444-444-444"
  },
  {
    name: "Tyrell",
    id: "5",
    number: "555-555-555"
  },
];

var div = "<div>";
for (var i = 0; i < users.length; i  ) {
  div  = "<p class='user-name'>"   users[i].name   "</p>";
  div  = "<p class='user-id'>"   users[i].id   "</p>";
  div  = "<p class='user-number'>"   users[i].number   "</p>";
}
div  = "</div>";
document.getElementById("usersList").innerHTML = div;
.user-name {
  color: red;
}

.user-id {
  color: blue;
}

.user-number {
  color: green;
}
<div class="contact-container">
  <div class="navbar">
    <ul>
      <li>
        <img src="https://img.icons8.com/ios-filled/50/000000/contact-card.png" />
      </li>
      <li>
        <a href="#">View</a>
      </li>
      <li>
        <a href="#">Add</a>
      </li>
      ...
    </ul>
  </div>
  <div class="users" id="usersList">

  </div>

CodePudding user response:

You could try creating your elements like this:

let div = document.createElement("div");
let p = document.createElement("p");

then add the class name:

p.className = "css class";

then add the parts to their parents:

div.appendChild(p);
document.getElementById("usersList").appendChild(div);

This is cleaner and more efficient than adding elements with innerHTML

CodePudding user response:

While you've already accepted an answer, I thought this might be an interesting opportunity to try to learn – for my own benefit, but hopefully to contribute an answer – about using custom elements.

So, with that in mind see the code below with its explanatory comments (though this remains something of a black-magic to me, hence my interest in working on it to formulate an answer):

// defining the custom-element, naming it 'user-card' which
// will lead to the element being a <user-card> element in the DOM:
customElements.define('user-card',
  class extends HTMLElement {
    constructor() {
      super();
      // we get the <template> element via its id (other
      // selection methods are available, of course):
      let template = document.getElementById('user-card');
      // and retrieve its content:
      let templateContent = template.content;

      // here we assign its shadow root as 'open', which
      // allows us - and JavaScript - to modify it:
      const shadowRoot = this.attachShadow({
          mode: 'open'
        })
        // and here we append the content of the <template>,
        // including its child nodes (the 'true' argument
        // to cloneNode()):
        .appendChild(templateContent.cloneNode(true));
    }
  }
);

// your data:
let users = [{
      name: "Jan",
      id: "1",
      number: "111-111-111"
    },
    {
      name: "Juan",
      id: "2",
      number: "222-222-222"
    },
    {
      name: "Margie",
      id: "3",
      number: "333-333-333"
    },
    {
      name: "Sara",
      id: "4",
      number: "444-444-444"
    },
    {
      name: "Tyrell",
      id: "5",
      number: "555-555-555"
    },
  ],
  userDiv = document.querySelector('#usersList');

// here we use Array.prototype.forEach() to iterate over the
// data, along with an anonymous Arrow function to pass the
// current user Object into the body of the function:
users.forEach(
  (user) => {
    // we create a new <user-card> element:
    let card = document.createElement('user-card'),
      // we create a new <li> element:
      li = document.createElement('li'),
      // we create a document fragment to contain the
      // HTML we're going to create to hopefully minimise
      // repaints:
      fragment = document.createDocumentFragment();

    // we then use Object.prototype.keys() to iterate over the
    // array of Object keys returned (in order to access the
    // contents of the user Object), and pass that key into
    // the body of the function:
    Object.keys(user).forEach(
      (key) => {
        // we create a clone of the <li> element:
        let clone = li.cloneNode();

        // we apply the class-name of the current key, so
        // each element gets a class of 'name', 'id' or 'number',
        // obviously other classes could be used but these made
        // the most sense given the context:
        clone.classList.add(key);

        // because the <style> of the <user-card> element's template
        // doesn't (seem to) apply to content added later, we use
        // CSSStlyleDeclaration.setProperty() to set the relevant
        // CSS properties of the cloned <li> element; here we
        // define the 'grid-area' property to properly place the
        // current element into the appropriate grid-area (defined
        // in the <template>):
        clone.style.setProperty('grid-area', key);

        // we add the property-value of the current Object key:
        clone.textContent = user[key];

        // and append the clone to the fragment, using
        // Element.append():
        fragment.append(clone);
      })
    // once all the data is within the document fragment, we
    // append that fragment to the <user-card> element:
    card.append(fragment);
    // and then append that <user-card> to the relevant ancestor
    // <div> in the document:
    userDiv.append(card);
  });
/* a very basic reset, to minimise cross-browser differences and
   and reset elements to their basic 'zero-style' state: */

*,
 ::before,
 ::after {
  box-sizing: border-box;
  font-size: 1rem;
  font-family: Calibri, Helvetica, Ubuntu, Arial, sans-serif;
  line-height: 1.4;
  margin: 0;
  padding: 0;
}

.users {
  /* specifying display: grid, since it's a typical (and
     relatively aesthetic) convention for 'cards': */
  display: grid;
  gap: 0.5em;
  /* allows the grid to adjust its layout to best fit the
     content within the constraints of the device: */
  grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
  margin: 1em auto;
  max-width: 90vw;
}
<!-- the template element that contains the structure to be re-used, with an id
     attribute for easy access via JavaScript, though other means of selection
     are possible -->
<template id="user-card">
<!-- because the defined style of the light DOM (or COM) doesn't penetrate
     into the shadow root we declare relevant CSS here, though there are
     concerns about this too; from experimentation the CSS declared here
     will target elements present in the <template> but not content added
     later, via JavaScript: -->
<style>
  ol {
    border: 1px solid #ccc;
     list-style-type: none;
     display: grid;
     gap: 0.5em;
     grid-template-areas:
       "id name name"
       "number number number";
     padding: 0.25em;
     margin: 0;
  }
</style>
  <!-- I've chosen to use an <ol> since the data seems to be
       ordered/structured: -->
  <ol>
    <!-- we use a <slot> element to contain the data we'll be appending
         (later) via JavaScript: -->
    <slot></slot>
  </ol>
</template>
<!-- for reasons of brevity I removed the extraneous content and retained
     only the minimal content relevant to the demo, which is why we have
     only the elements below: -->
<div class="contact-container">
  <div class="users" id="usersList"></div>
</div>

JS Fiddle demo.

References:

Bibliography:

  • Related