fix(ivy): support ICU messages inside <ng-container> (#27925)

PR Close #27925
This commit is contained in:
Pawel Kozlowski 2019-01-04 15:51:33 +01:00 committed by Kara Erickson
parent d80c32310a
commit 8a3cebde8b
2 changed files with 30 additions and 7 deletions

View File

@ -518,13 +518,12 @@ export function getRenderParent(tNode: TNode, currentView: LView): RElement|null
return nativeParentNode(currentView[RENDERER], getNativeByTNode(tNode, currentView));
}
const hostTNode = currentView[HOST_NODE];
const tNodeParent = tNode.parent;
const tNodeParent = getFirstNonICUParent(tNode);
if (tNodeParent != null && tNodeParent.type === TNodeType.ElementContainer) {
tNode = getHighestElementContainer(tNodeParent);
}
const hostTNode = currentView[HOST_NODE];
return tNode.parent == null && hostTNode !.type === TNodeType.View ?
getContainerRenderParent(hostTNode as TViewNode, currentView) :
getParentNative(tNode, currentView) as RElement;
@ -677,10 +676,12 @@ export function appendChild(
getBeforeNodeForView(index, views, lContainer[NATIVE]));
} else if (parentTNode.type === TNodeType.ElementContainer) {
const renderParent = getRenderParent(childTNode, currentView) !;
nativeInsertBefore(renderer, renderParent, childEl, parentEl);
const ngContainerAnchorNode = getNativeByTNode(parentTNode, currentView);
nativeInsertBefore(renderer, renderParent, childEl, ngContainerAnchorNode);
} else if (parentTNode.type === TNodeType.IcuContainer) {
const icuAnchorNode = getNativeByTNode(childTNode.parent !, currentView) !as RElement;
nativeInsertBefore(renderer, parentEl as RElement, childEl, icuAnchorNode);
const renderParent = getRenderParent(childTNode, currentView) !;
const icuAnchorNode = getNativeByTNode(parentTNode, currentView);
nativeInsertBefore(renderer, renderParent, childEl, icuAnchorNode);
} else {
isProceduralRenderer(renderer) ? renderer.appendChild(parentEl !as RElement, childEl) :
parentEl !.appendChild(childEl);

View File

@ -15,7 +15,7 @@ import {getNativeByIndex} from '../../src/render3/util';
import {NgIf} from './common_with_def';
import {element, elementEnd, elementStart, template, text, nextContext, bind, elementProperty, projectionDef, projection} from '../../src/render3/instructions';
import {element, elementEnd, elementStart, template, text, nextContext, bind, elementProperty, projectionDef, projection, elementContainerStart, elementContainerEnd} from '../../src/render3/instructions';
import {COMMENT_MARKER, ELEMENT_MARKER, I18nMutateOpCode, I18nUpdateOpCode, I18nUpdateOpCodes, TI18n} from '../../src/render3/interfaces/i18n';
import {HEADER_OFFSET, LView, TVIEW} from '../../src/render3/interfaces/view';
import {ComponentFixture, TemplateFixture} from './render_util';
@ -715,6 +715,28 @@ describe('Runtime i18n', () => {
'<div><span>3 <span title="emails label">emails</span><!--ICU 4--></span></div>');
});
it('for ICU expressions inside <ng-container>', () => {
const MSG_DIV = `{<7B>0<EFBFBD>, plural,
=0 {no <b title="none">emails</b>!}
=1 {one <i>email</i>}
other {<EFBFBD>0<EFBFBD> <span title="<22>1<EFBFBD>">emails</span>}
}`;
const fixture = prepareFixture(() => {
elementStart(0, 'div'); {
elementContainerStart(1); {
i18n(2, MSG_DIV);
}
elementContainerEnd();
}
elementEnd();
}, () => {
i18nExp(bind(0));
i18nApply(2);
}, 3, 1);
expect(fixture.html).toEqual('<div>no <b title="none">emails</b>!<!--ICU 4--></div>');
});
it('for nested ICU expressions', () => {
const MSG_DIV = `{<7B>0<EFBFBD>, plural,
=0 {zero}