-2

Is there a good way to iterate through an array of objects and apply those properties to multiple html elements with same classname?

I hope my example show more specific what I am trying to achieve. Thanks in advance!

var myObject = [{
    width: 100,
    text: "Hello World",
    bgColor: '#f00',
  },
  {
    width: 20,
    text: "Hi World",
    bgColor: "#0f0",
  }
];
const divs = document.getElementsByClassName("one");
console.log(divs);

myObject.forEach(function (arrayItem) {
    var x = arrayItem.width;
    var y = arrayItem.text;
    var z = arrayItem.bgColor;
    divs.style.width = x + '%';
    divs.innerHTML = y;
    divs.style.backgroundColor = z;
});
.contain {
  width: 500px;
  height: 100px;
  background: #666;
  padding: 20px;
}

.one {
  width: 100%;
  height: 50px;
  background: #aaa;
  display: flex;
  align-items: center;
}

.one:first-child {
  background: #ddd;
  width: 80%;
}

span {
  margin: 0 20px;
}
<div class="contain">
  <div class="one"><span>Should only read "Hello World", have red background and 100% width.</span></div>
  <div class="one"><span>Should only read "Hi World", have green background and 20% width.</span></div>
</div>
Frank351
  • 67
  • 2
  • 9
  • 1
    What did you try so far? – Omri Attiya Aug 25 '19 at 20:36
  • I don't see any attempt at looping through the input, or using the width / text/ bgColor properties. Please post what you've tried, so as to illustrate a specific roadblock you're running into in a [MCVE] - Stack Overflow is not a code-writing service – CertainPerformance Aug 25 '19 at 20:36
  • I did not succeed with looping. I have now added my failed code that I seek help with. Best regards. – Frank351 Aug 25 '19 at 20:55

3 Answers3

1

Your problem is that you are simply selecting divs which is an array and not selecting the nested div elements within it properly: divs[0];divs[1] etc.

If the amount of divs is dependent on the object children than a better way would be to generate the divs with JS rather than have them on the HTML to begin with:

  • html:
`<div class="contain" />
  • js:
const container = document.getElementsByClassName("contain")[0];

myObject.forEach(function (arrayItem) {
    let div = document.createElement('div');
    var x = arrayItem.width;
    var y = arrayItem.text;
    var z = arrayItem.bgColor;
    div.style.width = x + '%';
    div.innerHTML = y;
    div.style.backgroundColor = z;
    container.appendChild(div);
});

also adding a cleaner format of this code using object deconstruction:

myObject.forEach(function ({width, text, bgColor}) {
    let div = document.createElement('div');
    div.style.width = `${width}%`;
    div.innerHTML = text;
    div.style.backgroundColor = bgColor;
    container.appendChild(div);
});

aviya.developer
  • 3,343
  • 2
  • 15
  • 41
0

You have to iterate over myObject, but also to apply current index of the loop to your divs element array.

var myObject = [{
    width: 100,
    text: "Hello World",
    bgColor: '#f00',
  },
  {
    width: 20,
    text: "Hi World",
    bgColor: "#0f0",
  }
];
const divs = document.getElementsByClassName("one");
myObject.forEach(function (arrayItem, index) {
  if (index < divs.length) {
    var x = arrayItem.width;
    var y = arrayItem.text;
    var z = arrayItem.bgColor;
    divs[index].style.width = x + '%';
    divs[index].innerHTML = y;
    divs[index].style.backgroundColor = z;
  }
});
.contain {
  width: 500px;
  height: 100px;
  background: #666;
  padding: 20px;
}

.one {
  width: 100%;
  height: 50px;
  background: #aaa;
  display: flex;
  align-items: center;
}

.one:first-child {
  background: #ddd;
  width: 80%;
}

span {
  margin: 0 20px;
}
<div class="contain">
  <div class="one"><span>Should only read "Hello World", have red background and 100% width.</span></div>
  <div class="one"><span>Should only read "Hi World", have green background and 20% width.</span></div>
</div>
Nenad
  • 24,809
  • 11
  • 75
  • 93
0

.getElementsByClassName() has trouble with edge cases such as mutation and .length property when applied in a loop. The newer method is far better:

const divs = document.querySelectorAll(".one");

Apply .forEach() method to the NodeList returned from the statement above then refer to the array of objects and their properties on each iteration by using .forEach() second parameter which is the current index number of the NodeList. Keep in mind that divs is a NodeList of divs and that the first parameter of .forEach() represents the current div of the NodeList not the object in the array of objects.

 divs.forEach((node, index) => {...
   ...const x = cfg[index].width... /* cfg[index] the object at the 
   current index in the array of objects */
   ...node.style.width = x... //node is the current div

const cfg = [{
    width: 100,
    text: "Hello World",
    bgColor: '#f00',
  },
  {
    width: 20,
    text: "Hi World",
    bgColor: "#0f0",
  }
];
const divs = document.querySelectorAll(".one");
//console.log(divs);

divs.forEach((node, index) => {
  const x = cfg[index].width;
  const y = cfg[index].text;
  const z = cfg[index].bgColor;
  node.style.width = x + '%';
  node.textContent = y;
  node.style.backgroundColor = z;
});
.contain {
  width: 500px;
  height: 100px;
  background: #666;
  padding: 20px;
}

.one {
  width: 100%;
  height: 50px;
  background: #aaa;
  display: flex;
  align-items: center;
}

.one:first-child {
  background: #ddd;
  width: 80%;
}

span {
  margin: 0 20px;
}
<div class="contain">
  <div class="one"><span>Should only read "Hello World", have red background and 100% width.</span></div>
  <div class="one"><span>Should only read "Hi World", have green background and 20% width.</span></div>
</div>
zer00ne
  • 41,936
  • 6
  • 41
  • 68