Home > Enterprise >  Update an array by populating another array
Update an array by populating another array

Time:01-12

I need your help. I have an array of objects and an empty array that I need to add elements to. I am trying to output my finished items and the items I have in the cart. The fact is that I do not have the elements of the cart array displayed, although the elements are added to it. How can you update an array when elements are added to it and output them? Thank you very much

for (let element of arr) {
      let paragraph = document.createElement('p');
      paragraph.innerText = `${element.id}   ${element.name}   ${element.status}`;
      let button = document.createElement('button');
      button.innerText = 'Add to list';
      button.addEventListener('click', () => {
          if (!cart.includes(element)) {
              cart.push(element);
          }
      console.log(cart);
      })
      paragraph.appendChild(button);
      document.body.appendChild(paragraph);
  }

for (let element of cart) {
      let p = document.createElement('p');
      p.innerText = `${element.id}   ${element.name}   ${element.status}`;
      document.body.appendChild(p);
      console.log(p);
  }

CodePudding user response:

If we go through your current code step-by-step, we can see that (simply put):

  1. For every element in arr, a button is created that pushes something to cart.
  2. Then (immediately), for every element in cart, a paragraph is created.

After creating the paragraphs, cart may change again. But JavaScript is not a declarative language, so your for (let element of cart) loop won't react to future changes. Instead it is executed only once, when the program flow reaches that point.

That means you need to make the program flow reach the relevant code (creating a paragraph) again for every time it needs to run, i.e. every time something is pushed to cart.

And cart changes every time in the if-statement of the button's listener, so let's create a paragraph then:

const arr = [
  { id: 0, name: "Banana", status: "available" },
  { id: 1, name: "Apple", status: "sold out" },
];
const cart = [
  { id: 2, name: "Tomato", status: "fresh" }
];

for (let element of arr) {
  const p = document.createElement('p');
  p.innerText = `${element.id}   ${element.name}   ${element.status}`;
  const button = document.createElement('button');
  button.innerText = 'Add to list';
  button.addEventListener('click', () => {
    if (!cart.includes(element)) {
      cart.push(element);
      createParagraphFrom(element); // Add if not included yet
    }
    console.log("Cart:", cart);
  });
  p.appendChild(button);
  document.body.appendChild(p);
}

for (let element of cart) {
  createParagraphFrom(element); // Add initial cart contents
}

// Adding initial and eventual content works the same.
// This meaning we can use a function for this.
function createParagraphFrom(obj) {
  const p = document.createElement('p');
  p.innerText = `${obj.id}   ${obj.name}   ${obj.status}`;
  document.body.appendChild(p);
  console.log("Added paragraph:", p);
}


HTML elements can have custom data attributes that we can utilize. (Note that their values will always be of type string.)

When also using an element's children property, we won't need an extra backing array. That reduces redundant data and removes a point of confusion (which was your initial problem):

const list = document.getElementById("list");
const cart = document.getElementById("cart");

const listData = [
  { id: 0, name: "Banana", status: "freshly imported" },
  { id: 1, name: "Tomato", status: "just arrived" }
];

for (let element of listData) {
  addDataButton(element);
}

// ... (leaving out creation of initial cart content)

function addCartElement(data) {
  const element = document.createElement("li");
  // Copy relevant data (i.e. id) to P
  element.dataset.id = data.id;
  // Display (any) user-friendly text
  element.textContent = `${data.name}, ${data.status}`;
  
  cart.append(element);
}

function addDataButton(el) {
  const element = document.createElement("li");
  // Save data on element
  element.dataset.id = el.id;
  element.dataset.name = el.name;
  element.dataset.status = el.status;
  // Display (any) user-friendly text
  element.textContent = `${el.name}, ${el.status}`;
  
  const button = document.createElement("button");
  button.textContent = "Add to cart";
  button.addEventListener("click", () => {
    // Check if element with same ID exists in cart
    let existsInCart = false;
    for (let child of cart.children) {
      if (child.dataset.id === element.dataset.id) {
        // If child has same ID, then item exists in cart
        existsInCart = true;
        break;
      }
    }
    
    if (!existsInCart) {
      addCartElement(element.dataset);
    }
  });
  element.append(button);
  
  list.append(element);
}
<p>List</p>
<ul id="list"></ul>

<p>Cart</p>
<ul id="cart"></ul>

  • Related