I'm trying to achieve something to the rhyme of:
document.onload = init();
function Dropdown(dd) {
this.dd = dd;
this.exapnded = false;
this.list = dd.querySelector('.list');
this.changeState = changeState.bind(this);
this.dd.addEventListener('click', this.changeState(event));
}
function changeState(e) {
if(this.expanded == true) {
this.list.style.display = 'none';
this.expanded = false;
e.stopPropagation();
}
else {
this.list.style.display = 'block';
this.expanded = true;
e.stopPropagation();
}
}
function init() {
let ddCollection = document.getElementsByClassName('dropdown');
Array.from(ddCollection)
.forEach(function(ddElement) {
let dropdown = new Dropdown(ddElement);
console.log(dropdown);
}
);
}
But of course, for the miserable Javascript code I've written given my knowledge of it, when I attempt to execute the above code, it fails with
Uncaught TypeError: this.list is undefined
which implies that whatever I'm doing is not binding my this
object to the changeState function.
The result doesn't change if I attempt to try it as follows either
this.dd.addEventListener('click', changeState(event).bind(this));
In such a scenario, how do I achieve it? Vanilla Javascript answers only please.
I've been scratching my head over this and trying every possible solution available on StackOverflow but nothing seems to work. I hope I've conveyed my question appropriately enough. Please drop a comment below in case you need any further clarification.
You should just attach the function to Dropdown.prototype
rather than attaching it to the object instance:
Dropdown.prototype.changeState = function (e) {
if (this.expanded == true) {
this.list.style.display = 'none';
this.expanded = false;
e.stopPropagation();
} else {
this.list.style.display = 'block';
this.expanded = true;
e.stopPropagation();
}
};
Also, write the event listener like this, otherwise you immediately call the function instead of registering it for future click reaction.
this.dd.addEventListener('click', event => this.changeState(event));