Skip to content

Commit

Permalink
fix(ivy): inject ViewContainerRef for directives on ng-container (#25617
Browse files Browse the repository at this point in the history
)

PR Close #25617
  • Loading branch information
pkozlowski-opensource authored and matsko committed Aug 24, 2018
1 parent 18f129f commit b00038c
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 3 deletions.
3 changes: 2 additions & 1 deletion packages/core/src/render3/di.ts
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,8 @@ export function getOrCreateContainerRef(di: LInjector): viewEngine_ViewContainer
if (!di.viewContainerRef) {
const vcRefHost = di.node;

ngDevMode && assertNodeOfPossibleTypes(vcRefHost, TNodeType.Container, TNodeType.Element);
ngDevMode && assertNodeOfPossibleTypes(
vcRefHost, TNodeType.Container, TNodeType.Element, TNodeType.ElementContainer);
const hostParent = getParentLNode(vcRefHost) !;
const lContainer = createLContainer(hostParent, vcRefHost.view, true);
const comment = vcRefHost.view[RENDERER].createComment(ngDevMode ? 'container' : '');
Expand Down
5 changes: 4 additions & 1 deletion packages/core/src/render3/node_assert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@ export function assertNodeType(node: LNode, type: TNodeType) {
export function assertNodeOfPossibleTypes(node: LNode, ...types: TNodeType[]) {
assertDefined(node, 'should be called with a node');
const found = types.some(type => node.tNode.type === type);
assertEqual(found, true, `Should be one of ${types.map(typeName).join(', ')}`);
assertEqual(
found, true,
`Should be one of ${types.map(typeName).join(', ')} but got ${typeName(node.tNode.type)}`);
}

function typeName(type: TNodeType): string {
if (type == TNodeType.Projection) return 'Projection';
if (type == TNodeType.Container) return 'Container';
if (type == TNodeType.View) return 'View';
if (type == TNodeType.Element) return 'Element';
if (type == TNodeType.ElementContainer) return 'ElementContainer';
return '<unknown>';
}
47 changes: 46 additions & 1 deletion packages/core/test/render3/common_integration_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import {NgForOfContext} from '@angular/common';

import {AttributeMarker, defineComponent, templateRefExtractor} from '../../src/render3/index';
import {bind, template, elementEnd, elementProperty, elementStart, getCurrentView, interpolation1, interpolation2, interpolation3, interpolationV, listener, load, nextContext, restoreView, text, textBinding} from '../../src/render3/instructions';
import {bind, template, elementEnd, elementProperty, elementStart, getCurrentView, interpolation1, interpolation2, interpolation3, interpolationV, listener, load, nextContext, restoreView, text, textBinding, elementContainerStart, elementContainerEnd} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition';

import {NgForOf, NgIf, NgTemplateOutlet} from './common_with_def';
Expand Down Expand Up @@ -924,5 +924,50 @@ describe('@angular/common integration', () => {
expect(fixture.html).toEqual('');
});

it('should allow usage on ng-container', () => {
class MyApp {
showing = false;
static ngComponentDef = defineComponent({
type: MyApp,
factory: () => new MyApp(),
selectors: [['my-app']],
consts: 3,
vars: 1,
/**
* <ng-template #tpl>from tpl</ng-template>
* <ng-container [ngTemplateOutlet]="showing ? tpl : null"></ng-container>
*/
template: (rf: RenderFlags, myApp: MyApp) => {
if (rf & RenderFlags.Create) {
template(0, (rf1: RenderFlags) => {
if (rf1 & RenderFlags.Create) {
text(0, 'from tpl');
}
}, 1, 0, undefined, undefined, ['tpl', ''], templateRefExtractor);
elementContainerStart(2, [AttributeMarker.SelectOnly, 'ngTemplateOutlet']);
elementContainerEnd();
}
if (rf & RenderFlags.Update) {
const tplRef = load(1);
elementProperty(2, 'ngTemplateOutlet', bind(myApp.showing ? tplRef : null));
}
},
directives: () => [NgTemplateOutlet]
});
}

const fixture = new ComponentFixture(MyApp);
expect(fixture.html).toEqual('');

fixture.component.showing = true;
fixture.update();
expect(fixture.html).toEqual('from tpl');

fixture.component.showing = false;
fixture.update();
expect(fixture.html).toEqual('');

});

});
});

0 comments on commit b00038c

Please sign in to comment.