fix(ivy): type checking - apply attribute to property name mapping (#30675)
Some HTML attributes don't correspond to their DOM property name, in which case the runtime will apply the appropriate transformation when assigning a property using its attribute name. One example of this is the `for` attribute, for which the DOM property is named `htmlFor`. The type-checking machinery in ngtsc must also take this mapping into account, as it generates type-check code in which unclaimed property bindings are assigned to properties of (subtypes of) `HTMLElement`. Fixes #30607 Fixes FW-1327 PR Close #30675
This commit is contained in:
parent
812c231b0c
commit
4da5e9a156
|
@ -287,6 +287,19 @@ class TcbDirectiveOp extends TcbOp {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mapping between attributes names that don't correspond to their element property names.
|
||||
* Note: this mapping has to be kept in sync with the equally named mapping in the runtime.
|
||||
*/
|
||||
const ATTR_TO_PROP: {[name: string]: string} = {
|
||||
'class': 'className',
|
||||
'for': 'htmlFor',
|
||||
'formaction': 'formAction',
|
||||
'innerHtml': 'innerHTML',
|
||||
'readonly': 'readOnly',
|
||||
'tabindex': 'tabIndex',
|
||||
};
|
||||
|
||||
/**
|
||||
* A `TcbOp` which generates code to check "unclaimed inputs" - bindings on an element which were
|
||||
* not attributed to any directive or component, and are instead processed against the HTML element
|
||||
|
@ -324,7 +337,8 @@ class TcbUnclaimedInputsOp extends TcbOp {
|
|||
if (binding.type === BindingType.Property) {
|
||||
if (binding.name !== 'style' && binding.name !== 'class') {
|
||||
// A direct binding to a property.
|
||||
const prop = ts.createPropertyAccess(elId, binding.name);
|
||||
const propertyName = ATTR_TO_PROP[binding.name] || binding.name;
|
||||
const prop = ts.createPropertyAccess(elId, propertyName);
|
||||
const assign = ts.createBinary(prop, ts.SyntaxKind.EqualsToken, expr);
|
||||
this.scope.addStatement(ts.createStatement(assign));
|
||||
} else {
|
||||
|
|
|
@ -40,6 +40,11 @@ describe('type check blocks', () => {
|
|||
expect(tcb(TEMPLATE)).toContain('ctx.a[ctx.b];');
|
||||
});
|
||||
|
||||
it('should translate unclaimed bindings to their property equivalent', () => {
|
||||
const TEMPLATE = `<label [for]="'test'"></label>`;
|
||||
expect(tcb(TEMPLATE)).toContain('_t1.htmlFor = "test";');
|
||||
});
|
||||
|
||||
it('should generate a forward element reference correctly', () => {
|
||||
const TEMPLATE = `
|
||||
{{ i.value }}
|
||||
|
|
|
@ -765,8 +765,10 @@ export function generatePropertyAliases(tNode: TNode, direction: BindingDirectio
|
|||
}
|
||||
|
||||
/**
|
||||
* Mapping between attributes names that don't correspond to their element property names.
|
||||
*/
|
||||
* Mapping between attributes names that don't correspond to their element property names.
|
||||
* Note: this mapping has to be kept in sync with the equally named mapping in the template
|
||||
* type-checking machinery of ngtsc.
|
||||
*/
|
||||
const ATTR_TO_PROP: {[name: string]: string} = {
|
||||
'class': 'className',
|
||||
'for': 'htmlFor',
|
||||
|
|
Loading…
Reference in New Issue