0

I am trying to decrease the quantity by 1 from an object, I have created a function in the object called sell(), every time I am trying to call the function when a button is pressed I am not receiving any answer, this.quantity is not going down, I would need to find out how to call that function from outside the object.

class item {
  constructor(name, price, quantity) {
    this.name = name;
    this.price = price;
    this.quantity = quantity;
  }
  //this is the function i am trying to activate
  sell(e) {
    e.preventDefault();
    return `${this.name} ${this.price} ${this.quantity-1}`

  }
  store(count) {
    return `${this.name} ${this.price} ${this.quantity+count}`
  }
}
const items = [
  new item('soap', 11, 3),
  new item('bread', 12, 2),
  new item('apples', 13, 5),
  new item('banana', 15, 7),
  new item('grappe', 16, 5),
  new item('water', 9, 7),
  new item('beer', 4, 9),
];
for (let i = 0; i < items.length; i++) {
  const list = document.querySelector('.elements');
  const newLi = document.createElement('tr');
  newLi.innerHTML += `
    <td>${items[i].name}</td><td>${items[i].price}</td><td>${items[i].quantity}</td><button class="buyer">Buy</buy>`;
  list.appendChild(newLi);
  let btnBuy = newLi.querySelector('.buyer');
  //this is the listener that should activate sell(),
  btnBuy.addEventListener('click', sell);
}
<table class="elements">
  <thead>
    <th>Name</th>
    <th>Price</th>
    <th>Quantity</th>
  </thead>
  <tbody></tbody>
</table>

thanks to everyone I hope you can help

Alessio Cantarella
  • 5,077
  • 3
  • 27
  • 34
Joaquin86
  • 86
  • 9
  • One of the best things you can do is learn to use a debugger and set breakpoints. If you can do that and set a breakpoint in `sell`, you'd find that `this` does not point to the object you think it does. – Heretic Monkey May 19 '20 at 16:52
  • Does this answer your question? [How to access the correct \`this\` inside a callback?](https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback) – Heretic Monkey May 19 '20 at 16:53
  • @HereticMonkey OP didn't use ` btnBuy.addEventListener('click', items[i].sell)`, so the method won't even be called – Bergi May 19 '20 at 16:57
  • @Bergi then debugging would show that too, no? – Heretic Monkey May 19 '20 at 16:59
  • I am quite a beginer but happy to be learning, not even know how to set breackpoints, i tried with this btnBuy.addEventListener('click', item.sell); but still not working, what i am trying to do is to decrease the value in the object property by calling the function sell(), – Joaquin86 May 19 '20 at 17:10

1 Answers1

0

There is several problems in code:

1)btnBuy.addEventListener('click', sell);

sell is not defined, I'm assuming you need items[i].sell

2)items[i].sell in addEventListener will be called with button context: sell(e) { //... here this === button } there many options to fix this, my favorite is to use arrow function:

sell = (e) => {
  e.preventDefault();
  return `${this.name} ${this.price} ${this.quantity-1}`
}

3)you don't change anything in sell function to display your data, just returning string and no one use this data.

Here I think what you tried to achieve:

<html>
<body>

<table class="elements">
  <thead>
  <th>Name</th>
  <th>Price</th>
  <th>Quantity</th>
  </thead>
  <tbody class="elements-body"></tbody>
</table>

<script>
  class item {
    constructor(name, price, quantity) {
      this.name = name;
      this.price = price;
      this.quantity = quantity;
    }
    //this is the function i am trying to activate
    sell = () => {
      if (this.quantity > 0) {
        this.quantity--;
      }
      return `${this.name} ${this.price} ${this.quantity-1}`; //actually now you dont need this
    };

    store = (count) => {
      return `${this.name} ${this.price} ${this.quantity+count}`;
    }
  }
  const items = [
    new item('soap', 11, 3),
    new item('bread', 12, 2),
    new item('apples', 13, 5),
    new item('banana', 15, 7),
    new item('grappe', 16, 5),
    new item('water', 9, 7),
    new item('beer', 4, 9),
  ];

  const renderItems = (items) => {

    const list = document.querySelector('.elements-body');
    list.innerHTML = '';

    for (let i = 0; i < items.length; i++) {
      const newLi = document.createElement('tr');
      newLi.innerHTML += `<td>${items[i].name}</td><td>${items[i].price}</td><td>${items[i].quantity}</td><button class="buyer">Buy</buy>`;
      list.appendChild(newLi);
      let btnBuy = newLi.querySelector('.buyer');
      //this is the listener that should activate sell(),
      btnBuy.addEventListener('click', (e) => {
        e.preventDefault();
        items[i].sell();
        renderItems(items);
      });
    }
  };

  renderItems(items);

</script>

</body>
</html>
dark_gf
  • 684
  • 5
  • 15
  • 1
    thank you so much, I am so beginer that i can not even give a thumbs up, but it really helped, btnBuy.addEventListener('click', (e) => { e.preventDefault(); items[i].sell(); this is the lines of code i needed, with console.log(items[i]) i am abble alreay to see the changes – Joaquin86 May 19 '20 at 20:00