Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f4e6994

Browse files
feat(NgTemplateOutlet): add NgTemplateOutlet directive
This commits adds a new NgTemplateOutlet directive that can be used to create embeded views from a supplied TemplateRef. Closes angular#7615 Closes angular#8021
1 parent b602bd8 commit f4e6994

File tree

6 files changed

+146
-0
lines changed

6 files changed

+146
-0
lines changed

modules/angular2/src/common/directives.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
export {NgClass} from './directives/ng_class';
77
export {NgFor} from './directives/ng_for';
88
export {NgIf} from './directives/ng_if';
9+
export {NgTemplateOutlet} from './directives/ng_template_outlet';
910
export {NgStyle} from './directives/ng_style';
1011
export {NgSwitch, NgSwitchWhen, NgSwitchDefault} from './directives/ng_switch';
1112
export {NgPlural, NgPluralCase, NgLocalization} from './directives/ng_plural';

modules/angular2/src/common/directives/core_directives.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {CONST_EXPR, Type} from 'angular2/src/facade/lang';
22
import {NgClass} from './ng_class';
33
import {NgFor} from './ng_for';
44
import {NgIf} from './ng_if';
5+
import {NgTemplateOutlet} from './ng_template_outlet';
56
import {NgStyle} from './ng_style';
67
import {NgSwitch, NgSwitchWhen, NgSwitchDefault} from './ng_switch';
78
import {NgPlural, NgPluralCase} from './ng_plural';
@@ -50,6 +51,7 @@ export const CORE_DIRECTIVES: Type[] = CONST_EXPR([
5051
NgClass,
5152
NgFor,
5253
NgIf,
54+
NgTemplateOutlet,
5355
NgStyle,
5456
NgSwitch,
5557
NgSwitchWhen,
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import {Directive, Input, ViewContainerRef, ViewRef, TemplateRef} from 'angular2/core';
2+
import {isPresent} from 'angular2/src/facade/lang';
3+
4+
/**
5+
* Creates and inserts an embedded view based on a prepared `TemplateRef`.
6+
*
7+
* ### Syntax
8+
* - `<template [ngTemplateOutlet]="templateRefExpression"></template>`
9+
*/
10+
@Directive({selector: '[ngTemplateOutlet]'})
11+
export class NgTemplateOutlet {
12+
private _insertedViewRef: ViewRef;
13+
14+
constructor(private _viewContainerRef: ViewContainerRef) {}
15+
16+
@Input()
17+
set ngTemplateOutlet(templateRef: TemplateRef) {
18+
if (isPresent(this._insertedViewRef)) {
19+
this._viewContainerRef.remove(this._viewContainerRef.indexOf(this._insertedViewRef));
20+
}
21+
22+
if (isPresent(templateRef)) {
23+
this._insertedViewRef = this._viewContainerRef.createEmbeddedView(templateRef);
24+
}
25+
}
26+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import {
2+
AsyncTestCompleter,
3+
TestComponentBuilder,
4+
beforeEach,
5+
ddescribe,
6+
describe,
7+
el,
8+
expect,
9+
iit,
10+
inject,
11+
it,
12+
xit,
13+
} from 'angular2/testing_internal';
14+
15+
import {Component, Directive, TemplateRef, ContentChildren, QueryList} from 'angular2/core';
16+
17+
import {NgTemplateOutlet} from 'angular2/src/common/directives/ng_template_outlet';
18+
19+
export function main() {
20+
describe('insert', () => {
21+
it('should do nothing if templateRef is null',
22+
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
23+
var template = `<template [ngTemplateOutlet]="null"></template>`;
24+
tcb.overrideTemplate(TestComponent, template)
25+
.createAsync(TestComponent)
26+
.then((fixture) => {
27+
28+
fixture.detectChanges();
29+
expect(fixture.nativeElement).toHaveText('');
30+
31+
async.done();
32+
});
33+
}));
34+
35+
it('should insert content specified by TemplateRef',
36+
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
37+
var template =
38+
`<tpl-refs #refs="tplRefs"><template>foo</template></tpl-refs><template [ngTemplateOutlet]="currentTplRef"></template>`;
39+
tcb.overrideTemplate(TestComponent, template)
40+
.createAsync(TestComponent)
41+
.then((fixture) => {
42+
43+
fixture.detectChanges();
44+
expect(fixture.nativeElement).toHaveText('');
45+
46+
var refs = fixture.debugElement.children[0].getLocal('refs');
47+
48+
fixture.componentInstance.currentTplRef = refs.tplRefs.first;
49+
fixture.detectChanges();
50+
expect(fixture.nativeElement).toHaveText('foo');
51+
52+
async.done();
53+
});
54+
}));
55+
56+
it('should clear content if TemplateRef becomes null',
57+
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
58+
var template =
59+
`<tpl-refs #refs="tplRefs"><template>foo</template></tpl-refs><template [ngTemplateOutlet]="currentTplRef"></template>`;
60+
tcb.overrideTemplate(TestComponent, template)
61+
.createAsync(TestComponent)
62+
.then((fixture) => {
63+
64+
fixture.detectChanges();
65+
var refs = fixture.debugElement.children[0].getLocal('refs');
66+
67+
fixture.componentInstance.currentTplRef = refs.tplRefs.first;
68+
fixture.detectChanges();
69+
expect(fixture.nativeElement).toHaveText('foo');
70+
71+
fixture.componentInstance.currentTplRef = null;
72+
fixture.detectChanges();
73+
expect(fixture.nativeElement).toHaveText('');
74+
75+
async.done();
76+
});
77+
}));
78+
79+
it('should swap content if TemplateRef changes',
80+
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
81+
var template = `<tpl-refs #refs="tplRefs"><template>foo</template><template>bar</template></tpl-refs><template [ngTemplateOutlet]="currentTplRef"></template>`;
82+
tcb.overrideTemplate(TestComponent, template)
83+
.createAsync(TestComponent)
84+
.then((fixture) => {
85+
86+
fixture.detectChanges();
87+
var refs = fixture.debugElement.children[0].getLocal('refs');
88+
89+
fixture.componentInstance.currentTplRef = refs.tplRefs.first;
90+
fixture.detectChanges();
91+
expect(fixture.nativeElement).toHaveText('foo');
92+
93+
fixture.componentInstance.currentTplRef = refs.tplRefs.last;
94+
fixture.detectChanges();
95+
expect(fixture.nativeElement).toHaveText('bar');
96+
97+
async.done();
98+
});
99+
}));
100+
101+
});
102+
}
103+
104+
105+
@Directive({selector: 'tpl-refs', exportAs: 'tplRefs'})
106+
class CaptureTplRefs {
107+
@ContentChildren(TemplateRef) tplRefs: QueryList<TemplateRef>;
108+
}
109+
110+
@Component({selector: 'test-cmp', directives: [NgTemplateOutlet, CaptureTplRefs], template: ''})
111+
class TestComponent {
112+
currentTplRef: TemplateRef;
113+
}

modules/angular2/test/public_api_spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ var NG_COMMON = [
6666
'NgFormControl',
6767
'NgFormModel',
6868
'NgIf',
69+
'NgTemplateOutlet',
6970
'NgModel',
7071
'NgSelectOption',
7172
'NgStyle',

tools/public_api_guard/public_api_spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,9 @@ const COMMON = [
736736
'NgIf',
737737
'NgIf.constructor(_viewContainer:ViewContainerRef, _templateRef:TemplateRef)',
738738
'NgIf.ngIf=(newCondition:any)',
739+
'NgTemplateOutlet',
740+
'NgTemplateOutlet.constructor(_viewContainerRef:ViewContainerRef)',
741+
'NgTemplateOutlet.ngTemplateOutlet=(templateRef:TemplateRef)',
739742
'NgLocalization',
740743
'NgLocalization.getPluralCategory(value:any):string',
741744
'NgModel',

0 commit comments

Comments
 (0)