Search code examples
javascriptloopsobject

Setting attributes by looping through object keys and values


I have an object that I loop through with Object.keys and for each of those keys I want to set attributes that are also defined in that Object as an array of a key.

My code loops through the objects, sets the attribute but the for loop only sets the last index as an attribute so that all elements have the same attribute.

const headerElements = [
  {
    pageLinksHeader: document.createElement("div"),
    class: "page-links-header",
  },
  {
    companyNameHeader: document.createElement("div"),
    class: "company-name-header",
  },
  {
    mainPageLink: document.createElement("a"),
    text: "example",
    link: "../../index.html",
  },
  {
    webPagesHeader: document.createElement("div"),
    class: "webpages-header",
  },
  {
    webPageTarieven: document.createElement("a"),
    webPageReserveren: document.createElement("a"),
    webPageContact: document.createElement("a"),
  },
  {
    webPagesLinks: [
      "../../tarieven.html",
      "../../reseveren.html",
      "./contact.html",
    ],
    webPagesText: ["Tarieven", "Reserveren", "Contact"],
  },
];

Object.keys(headerElements[4]).forEach((attr) => {
  for (let i = 0; i < 3; i++) {
    headerElements[4][attr].setAttribute(
      "href",
      headerElements[5].webPagesLinks[i]
    );
  }
});

I tried different loops like I a do while where I thought it would take the first index at least but all just set the last index (i=3) as the attribute.

As far as I understand the for loop, loops through at the first key and then the forEach function goes on and sets all element attributes to i=3 because the for loop does not exit or return anything when i=1.

I want to understand if I can make it loop through correctly or if it isn't possible.


Solution

  • The issue is because within the forEach() over Object.keys() you are setting the href of the same element 3 times due to the for loop. Therefore each one will only ever contain the last value in the webPagesLinks array.

    To do what you require, remove the inner for loop and use the index from forEach() to set the href instead. You can use the same pattern to also set the text for each link too:

    Object.keys(headerElements[4]).forEach((attr, i) => {
      headerElements[4][attr].setAttribute("href", headerElements[5].webPagesLinks[i]);
      headerElements[4][attr].textContent = headerElements[5].webPagesText[i];
    });
    

    Here's a working example:

    const headerElements = [{pageLinksHeader:document.createElement("div"),class:"page-links-header"},{companyNameHeader:document.createElement("div"),class:"company-name-header"},{mainPageLink:document.createElement("a"),text:"example",link:"../../index.html"},{webPagesHeader:document.createElement("div"),class:"webpages-header"},{webPageTarieven:document.createElement("a"),webPageReserveren:document.createElement("a"),webPageContact:document.createElement("a")},{webPagesLinks:["../../tarieven.html","../../reseveren.html","./contact.html",],webPagesText:["Tarieven","Reserveren","Contact"]}];
    
    Object.keys(headerElements[4]).forEach((attr, i) => {
      headerElements[4][attr].setAttribute("href", headerElements[5].webPagesLinks[i]);
      headerElements[4][attr].textContent = headerElements[5].webPagesText[i];
    });
    
    console.log(headerElements[4]);