From b4b7af86c202cd82b751b3be4881f8a95ce5f6ca Mon Sep 17 00:00:00 2001 From: Olivier Combe Date: Wed, 5 Jun 2019 15:38:36 +0200 Subject: [PATCH] fix(ivy): trigger directive inputs for each template creation (#30870) A directive input that doesn't use a binding is triggered during the creation phase. But this was only executed at the first template pass, and not on subsequent ones. Now only the creation of the update instruction is executed on the first template pass, anything else is executed every time a template is created. FW-1361 #resolve PR Close #30870 --- packages/core/src/render3/i18n.ts | 14 +++++---- packages/core/test/acceptance/i18n_spec.ts | 36 ++++++++++++++++++++++ 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/packages/core/src/render3/i18n.ts b/packages/core/src/render3/i18n.ts index e04c076d80..a76f72c7eb 100644 --- a/packages/core/src/render3/i18n.ts +++ b/packages/core/src/render3/i18n.ts @@ -958,9 +958,7 @@ export function ɵɵi18n(index: number, message: string, subTemplateIndex?: numb export function ɵɵi18nAttributes(index: number, values: string[]): void { const tView = getLView()[TVIEW]; ngDevMode && assertDefined(tView, `tView should be defined`); - if (tView.firstTemplatePass && tView.data[index + HEADER_OFFSET] === null) { - i18nAttributesFirstPass(tView, index, values); - } + i18nAttributesFirstPass(tView, index, values); } /** @@ -985,8 +983,10 @@ function i18nAttributesFirstPass(tView: TView, index: number, values: string[]) // Even indexes are text (including bindings) const hasBinding = !!value.match(BINDING_REGEXP); if (hasBinding) { - addAllToArray( - generateBindingUpdateOpCodes(value, previousElementIndex, attrName), updateOpCodes); + if (tView.firstTemplatePass && tView.data[index + HEADER_OFFSET] === null) { + addAllToArray( + generateBindingUpdateOpCodes(value, previousElementIndex, attrName), updateOpCodes); + } } else { const lView = getLView(); elementAttributeInternal(previousElementIndex, attrName, value, lView); @@ -1001,7 +1001,9 @@ function i18nAttributesFirstPass(tView: TView, index: number, values: string[]) } } - tView.data[index + HEADER_OFFSET] = updateOpCodes; + if (tView.firstTemplatePass && tView.data[index + HEADER_OFFSET] === null) { + tView.data[index + HEADER_OFFSET] = updateOpCodes; + } } let changeMask = 0b0; diff --git a/packages/core/test/acceptance/i18n_spec.ts b/packages/core/test/acceptance/i18n_spec.ts index 81e56ac043..e1a8b742ba 100644 --- a/packages/core/test/acceptance/i18n_spec.ts +++ b/packages/core/test/acceptance/i18n_spec.ts @@ -715,6 +715,42 @@ onlyInIvy('Ivy i18n logic').describe('runtime i18n', () => { const element = fixture.nativeElement.firstChild; expect(element.title).toBe('Bonjour Angular'); }); + + it('should apply i18n attributes during second template pass', () => { + @Directive({ + selector: '[test]', + inputs: ['test'], + exportAs: 'dir', + }) + class Dir { + } + + @Component({ + selector: 'other', + template: `
` + }) + class Other { + } + + @Component({ + selector: 'blah', + template: ` + + + ` + }) + class Cmp { + } + + TestBed.configureTestingModule({ + declarations: [Dir, Cmp, Other], + }); + + const fixture = TestBed.createComponent(Cmp); + fixture.detectChanges(); + expect(fixture.debugElement.children[0].children[0].references.ref.test).toBe('Set'); + expect(fixture.debugElement.children[1].children[0].references.ref.test).toBe('Set'); + }); }); it('should work with directives and host bindings', () => {