Say I have a Web Component:
customElements.define("custom-list", class CustomList extends HTMLElement {
get filter() {
console.log("get filter");
return this.getAttribute("filter");
}
set filter(value) {
console.log("set filter");
this.setAttribute("filter", value);
}
});
I wanted to use the setter method to do some initial attribute validation, but the setter never gets called. I tried setting the attribute through the HTML:
<custom-list filter="some value"></custom-list>
Only when I use JavaScript to set a property programmatically does the setter get called:
var list = document.querySelector("custom-list");
list.filter = "some value";
list.setAttribute("filter", "some value"); // DOESN'T WORK EITHER
So, it seems like setting attributes through the HTML or using setAttribute
doesn't trigger the setter, which I partly can understand. My questions are:
connectedCallback
? Say I want to only accept a certain string, how would I detect that?filter
gets populated anyway, do I need the setter if I don't use JavaScript to set my attributes?Yes, at least if you want/need to run some tests/filtering upon the value you want to set.
Yep, connectedCallback or even in the constructor.
No, you don't
This being said if you need a clear control over your custom attributes, i would suggest creating an internal state that you populate once when your custom element is being created and then when attributeChangedCallback is being called. That would give you some advantages :
Here is an example :
customElements.define("custom-list", class CustomList extends HTMLElement {
static get observedAttributes() { return ['filter']; }
constructor() {
super();
this.state = {
filter: null
};
this.setFilter(this.getAttribute("filter"));
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === "filter") {
this.setFilter(newValue);
}
}
getFilter() {
console.log("get filter");
return this.state.filter;
}
setFilter(value) {
// You can add some logic here to control the value
console.log("set filter");
this.state.filter=value;
}
});
Then you can call the following to change your internal state :
list.setAttribute("filter", "some value");
Would be interrested to get some feedback on this from the community. Anyway, hope this helps :)