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
This commit is contained in:
parent
f440bd1793
commit
b4b7af86c2
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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) {
|
||||
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[])
|
|||
}
|
||||
}
|
||||
|
||||
if (tView.firstTemplatePass && tView.data[index + HEADER_OFFSET] === null) {
|
||||
tView.data[index + HEADER_OFFSET] = updateOpCodes;
|
||||
}
|
||||
}
|
||||
|
||||
let changeMask = 0b0;
|
||||
|
|
|
@ -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: `<div i18n #ref="dir" test="Set" i18n-test="This is also a test"></div>`
|
||||
})
|
||||
class Other {
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'blah',
|
||||
template: `
|
||||
<other></other>
|
||||
<other></other>
|
||||
`
|
||||
})
|
||||
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', () => {
|
||||
|
|
Loading…
Reference in New Issue