0

I want to create 100 elements inside div 'view', all with the same UI template as defined inside div 'personViewPane-template'.

I also have an array of 100 objects of class 'personViewPane' in js and each object is bound to its corresponding DOM element which was previously created so that I can manipulate each DOM element using the corresponding object's functions.

HTML

<head>
<style>
*{border:0;margin:0;padding:0;box-sizing:border-box;font-family:Calibri;}
.container{display:inline-block;height:170px;padding:5px;background:rgb(0,150,200);margin:5px;}
.image{width:140px;height:140px;background-size:cover;}
.text{width:140px;height:20px;text-align:center;color:white;}
</style>
</head>


<body>

<div id="view"></div>

<!--//////////////templates//////////////-->
<div style="display:none;">

<div id="personViewPane-template" >
<div id="{{componentID}}" class="container">
    <div class="image" style="background:red;"></div>
    <div class="text"></div>
</div>
</div>

</div>
<!--//////////end of templates////////////-->

</body>

Here is the flow

Inside loop

  • Create an object of personViewPane by calling constructor personViewPane(id,id_of_parent_Element)

Inside constructor

  • Load the html template into object by calling loadTemplate()
  • In the template, replace the field '{{componentID}}' with dynamically created id by calling render()
  • Add the template to the div 'view'
  • Get the newly added DOM element by calling createHandle() and store this in variable handle
  • Add event listeners to the DOM element by calling addListeners()
  • Add the variables to the DOM element by calling validateUI()

The problem is that addEventListener works only on last created element. I found similar questions such as this one where addEventListener is called inside loop but I want to have it invoked from the constructor.

Any ideas?

JavaScript

<script>

class pane
{
componentID="";
template="";
handle;

constructor()   
{this.componentID="";}

loadTemplate(x) 
{this.template=x;}

render()    
{this.template = this.template.replace('{{componentID}}',this.componentID);return this.template;}

createHandle()  
{this.handle=document.getElementById(this.componentID);}

getHandle() 
{return this.handle;}

}//end of class pane




class personViewPane extends pane
{
name="";

constructor(id, container)
{
    super();
    this.componentID=personViewPane.name+id;
    this.name = "user"+id;
    this.loadTemplate(document.getElementById('personViewPane-template').innerHTML);    
    document.getElementById(container).innerHTML+=this.render();
    this.createHandle();
    this.addListeners();
    this.validateUI();
}

validateUI(){this.getHandle().getElementsByClassName('text')[0].innerHTML= this.name;}

addListeners()
{
    var parent = this;
    var showName = function(){alert(parent.componentID);}
    this.getHandle().addEventListener( "click", showName);
}


}//end of class personViewPane



var p =[];

for(let i=0; i<100; i++)
{
p[i] = new personViewPane(i,'view');  // create objects
}

</script>

1 Answer 1

2

The problem with this code is

document.getElementById(container).innerHTML+=this.render();

It is actually replacing the old templates which has click listener with just templates. I used appendChild instead of innerHTML and it worked perfectly. As collateral effect I have changed loadTemplate, render and the constructor function.

loadTemplate(x) {
  this.template = x.cloneNode(true);
}

render() {
  this.template.setAttribute('id', this.componentID);
  return this.template;
}

constructor(id, container) {
  super();
  this.componentID = personViewPane.name + id;
  this.name = "user" + id;
  this.loadTemplate(
    document.getElementById("personViewPane-template").firstElementChild
  );
  document.getElementById(container).appendChild(this.render());
  this.createHandle();
  this.addListeners();
  this.validateUI();
}

I tried out the same in code pen. Here is the link to it.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.