I have this custom HTML element causing me trouble. Down in the StaffList connectedCallback() function, i have to call and outside function of the parrent but the super keyword for addStaff() is giving me an error. "Uncaught SyntaxError: use of super property accesses only valid within methods or eval code within methods". How can i access something outside the request?
class StaffList extends HTMLElement {
// A getter/setter for a disabled property.
get selected() {
return this.hasAttribute('selected');
}
set selected(val) {
// Reflect the value of the disabled property as an HTML attribute.
if (val) {
this.setAttribute('selected', '');
} else {
this.removeAttribute('selected');
}
}
constructor() {
// If you define a constructor, always call super() first!
// This is specific to CE and required by the spec.
super();
/* handle clicks */
for (const item of this.children) {
item.addEventListener('click', e => {
console.log(e);
});
}
}
connectedCallback() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
for (var item of JSON.parse(this.responseText)) {
console.log(item);
this.addStaff(item);
}
}
};
xhttp.open('GET', "/api/get_staff");
xhttp.send();
}
}
addStaff() {
console.log("add staff");
}
customElements.define('staff-list', StaffList);
I tried the keyword this but gives me the XML request object instead of my custom element.
2
Answers
The problem here is caused by
this
is not bounded to the class instance that you created as you have expected. When you create a function withfunction() {
constructor, it will create a new scope and bound to whoever that called it, in this case since it is called byXMLHttpRequest
, it will will be bound to it instead.There are 2 solutions in your case, a solution would be setting
this
into another constant such asself
which you can then refer in yourfunction() {
in your XMLHTTPRequest.Another solution is to use anonymous function which doesn’t depends on the caller. However, you wouldn’t be able to use
this
to refer toxhttp
but rather you need to usexhttp
directly.I would really recommend switching from using XMLHttpRequest to fetch, but that is not the question.
And from var to let and there seems to be a closing bracket too much after connectedCallback…?
But that is none of my business 😉
Now for the main problem:
In JavaScript a function creates a new this scope, unless it is an arrow function.
You are using a traditional / non-arrow function for your onreadystatechange (and you need to do so, because this inside this function is the xhttp object, an instance of XMLHttpRequest. The problem is: You want to access the instance of your class from inside this function as well.
The traditional trick for this (pun intended) is storing the instance of your class in another variable before going into the the ‘inner’ function, I usually call this variable that (for fun). Keep a lookout for that in the following code: