Undesirable ng-attr-disabled behavior on custom elements #16602
Description
I'm submitting a ...
- bug report
- feature request
- other
Current behavior:
ng-attr
conditionally sets attributes. For most attributes, including ad hoc custom attributes, this means that if the expression interpolates to a string, that attribute will be set with that string as its value. But certain attributes, such as disabled
, are recognized specifically and have different behavior. On some elements (e.g. button
, input
, etc.) disabled
is a boolean HTML attribute and valid HTML requires it be either <button disabled>
or <button disabled="disabled">
. And that's how ng-attr-disabled
behaves. But disabled
isn't a global attribute and these semantics and rules really only apply for the standard HTML elements that are specified with the standard disabled
attribute.
I have defined a Custom Element that observes a disabled
attribute. But due to this behavior, consumers of my Custom Element can't use ng-attr
on that custom element for the disabled
attribute, because instead of outputting the value they're trying to set, the string disabled
always gets output instead.
Actually, it's "worse" than I originally thought. There's no way to set any other value with Angular. See final section.
Expected / new behavior:
React has some similar issues affecting support for Web Components where it attempts to provide value to developers by throwing errors when standard HTML elements and attributes are used in invalid ways in JSX. My loose understanding is that React now checks for a hyphen, assumes any tag with hyphen in its name is a custom element, and goes down a different path without its potentially disruptive HTML validation behavior for those.
I think it might be preferable if ngAttr
and ngDisabled
(among, probably, some other directives) did something similar. The enforcement of disabled="disabled"
should really only apply on standard HTML elements, not on Custom Elements.
Especially since, without the draconian error handling of serving XHTML as XML (perhaps even with it, I don't recall, it's been so long), it really doesn't matter what the value is for any element. Strictly speaking, it's invalid, but practically speaking, you can write the HTML <button disabled="woooooooo!!!">
and it's handled the same in browsers as <button disabled="disabled">
.
Minimal reproduction of the problem with instructions:
https://codepen.io/morewry/pen/QxqrmJ
AngularJS version: 1.6.7, 1.7.3
Browser: all
Anything else:
I get that this could be problematic since it's a change in how Angular has behaved for a long time. It's a pain for using Web Components with Angular as-is, however, because it's almost impossible to work around without changing the attribute name, since the behavior shows up in all of the following:
- When using
ng-attr-disabled
- When using
ng-disabled
- When using
disabled
with interpolation, e.g.disabled="{{something}}"
But there's no particular reason this attribute name should have to change. The best vocabulary choice is disabled
, not disable
, not disabled-whatever
or whatever-disabled
, in part because it's familiar.