From 204620291e2c8de29cfbed7cf74d401ef376d413 Mon Sep 17 00:00:00 2001 From: Andrew Kushnir Date: Tue, 5 Nov 2019 11:12:27 -0800 Subject: [PATCH] fix(ivy): better support for i18n attributes on s (#33599) Prior to this commit, i18n runtime logic used `elementAttributeInternal` function (that uses `setAttribute` function under the hood) for all elements where i18n attributes are present. However the `` elements in a template may also have i18n attributes and calling `setAttribute` fails, since they are represented as comment nodes in DOM. This commit ensures that we call `setAttribute` on nodes with TNodeType.Element type (that support that operation) only. PR Close #33599 --- packages/core/src/render3/i18n.ts | 8 +++++-- packages/core/test/acceptance/i18n_spec.ts | 27 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/packages/core/src/render3/i18n.ts b/packages/core/src/render3/i18n.ts index cce8dc5243..73453cc179 100644 --- a/packages/core/src/render3/i18n.ts +++ b/packages/core/src/render3/i18n.ts @@ -1011,9 +1011,13 @@ function i18nAttributesFirstPass(lView: LView, tView: TView, index: number, valu generateBindingUpdateOpCodes(value, previousElementIndex, attrName), updateOpCodes); } } else { - elementAttributeInternal(previousElementIndex, attrName, value, lView); - // Check if that attribute is a directive input const tNode = getTNode(previousElementIndex, lView); + // Set attributes for Elements only, for other types (like ElementContainer), + // only set inputs below + if (tNode.type === TNodeType.Element) { + elementAttributeInternal(previousElementIndex, attrName, value, lView); + } + // Check if that attribute is a directive input const dataValue = tNode.inputs && tNode.inputs[attrName]; if (dataValue) { setInputsForProperty(lView, dataValue, value); diff --git a/packages/core/test/acceptance/i18n_spec.ts b/packages/core/test/acceptance/i18n_spec.ts index afab875496..bd01f90502 100644 --- a/packages/core/test/acceptance/i18n_spec.ts +++ b/packages/core/test/acceptance/i18n_spec.ts @@ -1268,6 +1268,33 @@ onlyInIvy('Ivy i18n logic').describe('runtime i18n', () => { expect(comp.attributes['messagetext']).toBe('Bonjour'); expect(comp.attributes['ng-reflect-message-text']).toBe('Bonjour'); }); + + it('should support i18n attributes on elements', () => { + loadTranslations({[computeMsgId('Hello', 'meaning')]: 'Bonjour'}); + + @Directive({selector: '[mydir]'}) + class Dir { + @Input() mydir: string = ''; + } + + @Component({ + selector: 'my-cmp', + template: ` + + `, + }) + class Cmp { + } + + TestBed.configureTestingModule({ + declarations: [Cmp, Dir], + }); + const fixture = TestBed.createComponent(Cmp); + fixture.detectChanges(); + + const dir = fixture.debugElement.childNodes[0].injector.get(Dir); + expect(dir.mydir).toEqual('Bonjour'); + }); }); it('should work with directives and host bindings', () => {