Let me preface this by saying that I've never really used Angular before. I'm trying to debug a problem one of the users of my web component library is facing.
I have a custom element, using lit-element, that has a boolean property. That boolean property has a custom attribute converter that makes it treat the string "false" as falsy (as opposed to native html element boolean attributes where the presence of the attribute makes it true). The converter looks like this:
{
fromAttribute(val) {
if (val === 'false') {
return false;
}
if (val === '') {
return true;
}
return Boolean(val);
},
toAttribute(val) {
if (!val) {
return null;
}
return '';
}
}
As far as I can tell, Angular has 2 ways of binding a value to an html element in the template:
enabled="{{ enabled }}"
[enabled]="enabled"
For native elements like <img>
, the attribute binding works as expected - I can see the attribute when I inspect the html.
For custom elements, attributes don't appear to be set at all - Angular seems to be setting a property no matter what. But, it is stringifying the value.
Here's a stackblitz that tries to demonstrate this: https://stackblitz.com/edit/angular-lit-element-1vz1nf?file=src%2Fapp%2Fapp.component.ts
I have a custom <hello-world>
component that accepts a name
, and enabled
. If you inspect the html, name is not set as an attribute at all. enabled
is set, but not to the value I'd expect.
There's also an <img>
tag, where src
is being set correctly.
Does angular special case custom elements and only ever set properties? Is this documented somewhere? To me it feels like a bug, and breaks some people's code who are using my custom elements in Angular.
To bind to attributes, you need to use the [attr.*]
binding, otherwise you are binding to properties of the element, or @Input()
of the custom element/component. In your example this would look like:
<hello-world name="{{ name }}" [attr.enabled]="enabled"></hello-world>
stack
You also have the @Attribute()
decorator. I've added an example of it to the stack. I don't know how this would look like in a custom element. I do know that you can't do dynamic binding to it. The value needs to be fixed, and needs to be string
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With