Issue
I'm new with Web Component and i've a problem when i write a component in html and add an attribute directly in html. The problem is that the component doesn't trigger the set property function.
Only if i set the attribute or create the component with javascript and add it to the DOM, the set property function works.
I've created a pen to give an example of my problem:
window.addEventListener('load', () => {
document.body.getElementsByTagName('news-article')[1].article = {
title: 'dynamic value'
};
let element = document.createElement('news-article');
element.article = {
'title': 'dynamic element'
};
document.body.appendChild(element);
})
class NewsArticle extends HTMLElement {
static get observedAttributes() {
debugger
return ['article'];
}
constructor() {
debugger
super();
this.root = this.attachShadow({
mode: 'open'
});
}
set article(val) {
debugger
this.root.innerHTML = `
<style>
:host {
display: block;
border: 3px solid #000;
padding: 15px;
}
h2 {
text-transform: uppercase;
}
</style>
<h2>${val.title}</h2>
`;
}
get article() {
debugger
return this.getAttribute('article');
}
attributeChangedCallback(attrName, oldVal, newVal) {
debugger
this.setAttribute(attrName) = JSON.parse(newVal);
}
}
window.customElements.define('news-article', NewsArticle);
<news-article article="{ title: 'static value' }"></news-article>
<news-article></news-article>
Solution
setAttribute
takes two arguments, instead you're assigning JSON.parse(newVal)
to whatever this.setAttribute(attrName)
returns (I assume undefined
).
this.setAttribute(attrName) = JSON.parse(newVal);
must be
this.setAttribute(attrName, JSON.parse(newVal));
On top of that, note that { title: 'static value' }
is not valid JSON. You cannot use single quotes to quote keys or values. It must be double quotes.
Next, it does not make sense to do this.setAttribute(attrName, JSON.parse(newVal))
in your attributeChangedCallback
for two reasons:
- The attribute is already in the process of being set to that (which is why your
attributeChangedCallback
is being executed) - Attributes can only contain
String
values.
Instead, what you want to do is
this.article = JSON.parse(newVal);
which will trigger your getter (which is what you want, because it's that what really updates your component).
I assume your misunderstanding results from you assuming that custom attributes are automatically synchronized with a same-name property - which is not the case.
window.addEventListener('load', () => {
document.body.getElementsByTagName('news-article')[1].article = {
title: 'dynamic value'
};
let element = document.createElement('news-article');
element.article = {
'title': 'dynamic element'
};
document.body.appendChild(element);
})
class NewsArticle extends HTMLElement {
static get observedAttributes() {
return ['article'];
}
constructor() {
super();
this.attachShadow({
mode: 'open'
});
}
set article(val) {
this.shadowRoot.innerHTML = `
<style>
:host {
display: block;
border: 3px solid #000;
padding: 15px;
}
h2 {
text-transform: uppercase;
}
</style>
<h2>${val.title}</h2>`;
}
get article() {
return this.getAttribute('article');
}
attributeChangedCallback(attrName, oldVal, newVal) {
this.article = JSON.parse(newVal);
}
}
window.customElements.define('news-article', NewsArticle);
<news-article article='{ "title": "static value" }'></news-article>
<news-article></news-article>
<news-article article='{ "title": "static value" }'></news-article>
Answered By - connexo
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.