I'm learning the ways of scoping and inheritance and am having a little difficulty retrieving the instance of a class of which a DOM element is a property. There is a Parent and lets say there can be unlimited Child(ren). Is there any way of getting the instance via an event delegate? Hopefully the following will help explain:
class Parent {
constructor() {
this.element = document.createElement('div');
this.element.setAttribute('class', 'parent');
// add elements from instances
this.element.appendChild(new Child(1, this).element);
this.element.appendChild(new Child(2, this).element);
this.element.appendChild(new Child(3, this).element);
// event delegate
this.element.addEventListener('click', (e) => {
// would like to get the particular instance of the class "Child" that was clicked
});
}
something(id) {
console.log('something', id);
}
}
class Child {
constructor(id, parentReference) {
this.id = id;
this.element = document.createElement('div');
this.element.setAttribute('class', 'child');
// would like to avoid adding a click event for each and use the parent as delegate
this.element.addEventListener('click', () => {
parentReference.something(this.id)
});
}
}
Hope this makes sense, welcome any and all feedback.
Also on another note, since I'm not storing the instances anywhere, only creating and appending an element to the DOM, will the Child instance remain intact as long as the DOM element remains rendered and other properties get used then be garbage collected? Should they be stored elsewhere, like an array to be safe?
Thanks in advance!
Looks like what you're trying to do is actually Web Components : you could just make your class extend HTMLElement and benefit from the whole lifecycle which comes natively with custom elements.
For example, you could have a Parent
component which holds some Child
components. As Parent
and Child
classes would be real HTMLElements, if you register a click event listener in the Parent
object, you will receive click events triggered on the childs. And the clicked child instance will be available in the target property of the click event.
class ParentElement extends HTMLElement {
constructor() {
super();
this.classList.add('parent');
// add elements from instances
this.innerHTML = `
<child-element data-sequence="1"></Child>
<child-element data-sequence="2"></Child>
<child-element data-sequence="3"></Child>
`;
// event delegate
this.addEventListener('click', (e) => {
// Child instance is available in the event itself
const child = e.target;
this.something(child.id);
});
}
something(id) {
console.log('something', id);
}
}
window.customElements.define('parent-element', Parent);
class ChildElement extends HTMLElement {
constructor() {
super()
this.id = this.dataset.sequence;
this.classList.add('child');
}
}
window.customElements.define('child-element', ChildElement);
Then you can just append the parent element into the dom :
document.body.appendChild(new ParentElement());
(Be careful, i didn't tested the previous example, this is just to give you an idea)
But maybe i get it wrong. In this case, i would suggest to avoid keeping a reference to a dom element into custom objects as it would probably be easy to get memory leaks (if you re render some portion of your page but keep references to Parent
or Child
instances then you'll also keep a reference to the corresponding dom node). Couldn't you go the other way around by attaching your custom objects onto dom nodes (a bit like a controller ?)
Hope this help,