Home > Blockchain >  Make JavaScript wait until element is rendered on the page an after bind JS object to it
Make JavaScript wait until element is rendered on the page an after bind JS object to it

Time:11-06

I have working on some kind of project and it's requires dynamic fron-end elements, but I don't have time to learn React or something else. So, i decided to write some mini-logic which implies that I adding some element to my DOM and after tie some JS object to it that represents it's logic and provide it's methods. Below you can see the example that exlain my question.

`

function itemHTML(name,price){
  return  `
    <div >
      <span >${name}</span>
      <span >${price}$</span>
      <button >X</button> 
    </div>
  `
}

class ContainerObj {
  constructor (self){
    this.self = self
    this.items = []
  }
  add(item) {
    this.self.innerHTML  = itemHTML(item.name,item.price)
    this.items.push(
      new ItemObj(
        self = this.self.querySelector(".item:last-child")
      )
    )
  }
}

class ItemObj {
  constructor(self){
    this.self = self 
    this._name = self.querySelector(".item__name")
    this._price = self.querySelector(".item__price")
    this._deleteButton = self.querySelector(".item__delete-button")
    this._deleteButton.addEventListener("click",(event)=>{
      this.self.remove()
    })
  }
  get name() {
    return this._name
  }
  get price() {
    return this._price
  }
  set name(value) {
      this._name = value
  }
  set price(value) {
      this._price = value
  }
}

class AppenderObj {
  constructor (self,container) {
    this.self = self
    this.container = container 
    this._name = self.querySelector(".appender__name")
    this._price = self.querySelector(".appender__price")
    this._addButton = self.querySelector(".appender__add-button")
    this._addButton.addEventListener("click",(event)=>{
        this.container.add({
          name:this._name.value,
          price:this._price.value
        })
        this._name.value = ""
        this._price.value = ""
    })
  }
}

items = [
  {
    name: "Apple",
    price: 5
  },
  {
    name: "Pen",
    price: 20
  }
];

$container = new ContainerObj(
  self = document.querySelector("#container")
)

$appender = new AppenderObj(
  self = document.querySelector("#appender"),
  container = $container
)


items.forEach((item)=>{
  $container.add(item)
})
#container{
  border:1px solid black;
}
#appender{
  margin-top: 10px;
}
.item{
  display: flex;
  justify-content: space-between;
  border: 1px solid black;
  margin: 5px;
  padding: 5px;
}
<div id="container">    </div>
<div id="appender">
    <input class="appender__name" type="text" placeholder="Name">
    <input class="appender__price" type="text" placeholder="Price">
    <input class="appender__add-button" type="button" value="add">
</div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

`

I can't understand why it's adding truly but can't

Thanks for advices... Trying to write less :) If there is not enough information about issue, i'll send the rest.

CodePudding user response:

The problem lies in the concatenation of the HTML where you do this.self.innerHTML = itemHTML(item.name,item.price) within the ContainerObj class. If you were to use insertAdjactentHTML instead, like this:

this.self.insertAdjacentHTML('beforeend', itemHTML( item.name, item.price ) );

The event listeners will function correctly.

function itemHTML(name,price){
  return  `
    <div >
      <span >${name}</span>
      <span >${price}$</span>
      <button >X</button> 
    </div>
  `;
};

class ContainerObj {
  constructor(n){
    this.self=n;
    this.items=[];
  }
  
  add(item) {
    /* do not concatenate the HTML, insert new like this */
    this.self.insertAdjacentHTML('beforeend', itemHTML( item.name, item.price ) );
    this.items.push(
      new ItemObj( this.self.querySelector(".item:last-child") )
    )
  }
};

class ItemObj {
  constructor(n){
    this._name = n.querySelector(".item__name");
    this._price = n.querySelector(".item__price");
    this._deleteButton = n.querySelector(".item__delete-button");
    
    this._deleteButton.addEventListener("click",(event)=>{
      n.remove();
    })
  }
  get name() {
    return this._name;
  }
  get price() {
    return this._price;
  }
  set name(value) {
      this._name = value;
  }
  set price(value) {
      this._price = value;
  }
};

class AppenderObj {
  constructor (n,container) {
    this.container = container;
    this._name = n.querySelector(".appender__name");
    this._price = n.querySelector(".appender__price");
    this._addButton = n.querySelector(".appender__add-button");
    
    this._addButton.addEventListener("click",(event)=>{
        this.container.add({
          name:this._name.value,
          price:this._price.value
        })
        
        this._name.value = "";
        this._price.value = "";
    });
  }
};


$container = new ContainerObj(
  document.querySelector("#container")
);
$appender = new AppenderObj(
  document.querySelector("#appender"),$container
);



const items = [
  {
    name: "Apple",
    price: 5
  },
  {
    name: "Pen",
    price: 20
  }
];

items.forEach(item=>{
  $container.add(item)
});
#container{
  border:1px solid black;
}
#appender{
  margin-top: 10px;
}
.item{
  display: flex;
  justify-content: space-between;
  border: 1px solid black;
  margin: 5px;
  padding: 5px;
}
<div id="container"></div>
<div id="appender">
    <input class="appender__name" type="text" placeholder="Name" />
    <input class="appender__price" type="text" placeholder="Price" />
    <input class="appender__add-button" type="button" value="add" />
</div>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related