fix(ivy): handle elements with local refs in i18n blocks (#33415)
Prior to this commit, i18n logic which ensures that elements removed in a translation are also removed in DOM, didn't take into account the fact that elements may have local refs. As a result, remove operation failed, since there is no corresponding tNode found. This commit updates the logic to skip all local refs while going though the list of nodes to ensure that DOM matches elements present in translation. PR Close #33415
This commit is contained in:
parent
da4eb91283
commit
bd40c89688
|
@ -683,10 +683,21 @@ function i18nEndFirstPass(lView: LView, tView: TView) {
|
|||
const visitedNodes = readCreateOpCodes(rootIndex, tI18n.create, lView);
|
||||
|
||||
// Remove deleted nodes
|
||||
for (let i = rootIndex + 1; i <= lastCreatedNode.index - HEADER_OFFSET; i++) {
|
||||
if (visitedNodes.indexOf(i) === -1) {
|
||||
removeNode(i, lView, /* markAsDetached */ true);
|
||||
let index = rootIndex + 1;
|
||||
while (index <= lastCreatedNode.index - HEADER_OFFSET) {
|
||||
if (visitedNodes.indexOf(index) === -1) {
|
||||
removeNode(index, lView, /* markAsDetached */ true);
|
||||
}
|
||||
// Check if an element has any local refs and skip them
|
||||
const tNode = getTNode(index, lView);
|
||||
if (tNode && (tNode.type === TNodeType.Element || tNode.type === TNodeType.ElementContainer) &&
|
||||
tNode.localNames !== null) {
|
||||
// Divide by 2 to get the number of local refs,
|
||||
// since they are stored as an array that also includes directive indexes,
|
||||
// i.e. ["localRef", directiveIndex, ...]
|
||||
index += tNode.localNames.length >> 1;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -287,6 +287,43 @@ onlyInIvy('Ivy i18n logic').describe('runtime i18n', () => {
|
|||
expect(instance.clicks).toBe(1);
|
||||
});
|
||||
|
||||
it('should support local refs inside i18n block', () => {
|
||||
loadTranslations({
|
||||
[computeMsgId(
|
||||
'{$START_TAG_NG_CONTAINER} One {$CLOSE_TAG_NG_CONTAINER}' +
|
||||
'{$START_TAG_DIV} Two {$CLOSE_TAG_DIV}' +
|
||||
'{$START_TAG_SPAN} Three {$CLOSE_TAG_SPAN}')]:
|
||||
'{$START_TAG_NG_CONTAINER} Une {$CLOSE_TAG_NG_CONTAINER}' +
|
||||
'{$START_TAG_DIV} Deux {$CLOSE_TAG_DIV}' +
|
||||
'{$START_TAG_SPAN} Trois {$CLOSE_TAG_SPAN}'
|
||||
});
|
||||
const fixture = initWithTemplate(AppComp, `
|
||||
<div i18n>
|
||||
<ng-container #localRefA> One </ng-container>
|
||||
<div #localRefB> Two </div>
|
||||
<span #localRefC> Three </span>
|
||||
</div>
|
||||
`);
|
||||
expect(fixture.nativeElement.textContent).toBe(' Une Deux Trois ');
|
||||
});
|
||||
|
||||
it('should handle local refs correctly in case an element is removed in translation', () => {
|
||||
loadTranslations({
|
||||
[computeMsgId(
|
||||
'{$START_TAG_NG_CONTAINER} One {$CLOSE_TAG_NG_CONTAINER}' +
|
||||
'{$START_TAG_DIV} Two {$CLOSE_TAG_DIV}' +
|
||||
'{$START_TAG_SPAN} Three {$CLOSE_TAG_SPAN}')]: '{$START_TAG_DIV} Deux {$CLOSE_TAG_DIV}'
|
||||
});
|
||||
const fixture = initWithTemplate(AppComp, `
|
||||
<div i18n>
|
||||
<ng-container #localRefA> One </ng-container>
|
||||
<div #localRefB> Two </div>
|
||||
<span #localRefC> Three </span>
|
||||
</div>
|
||||
`);
|
||||
expect(fixture.nativeElement.textContent).toBe(' Deux ');
|
||||
});
|
||||
|
||||
describe('ng-container and ng-template support', () => {
|
||||
it('should support ng-container', () => {
|
||||
loadTranslations({[computeMsgId('text')]: 'texte'});
|
||||
|
|
Loading…
Reference in New Issue