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 #7615 Closes #8021
This commit is contained in:
parent
b602bd8c83
commit
f4e6994634
|
@ -6,6 +6,7 @@
|
|||
export {NgClass} from './directives/ng_class';
|
||||
export {NgFor} from './directives/ng_for';
|
||||
export {NgIf} from './directives/ng_if';
|
||||
export {NgTemplateOutlet} from './directives/ng_template_outlet';
|
||||
export {NgStyle} from './directives/ng_style';
|
||||
export {NgSwitch, NgSwitchWhen, NgSwitchDefault} from './directives/ng_switch';
|
||||
export {NgPlural, NgPluralCase, NgLocalization} from './directives/ng_plural';
|
||||
|
|
|
@ -2,6 +2,7 @@ import {CONST_EXPR, Type} from 'angular2/src/facade/lang';
|
|||
import {NgClass} from './ng_class';
|
||||
import {NgFor} from './ng_for';
|
||||
import {NgIf} from './ng_if';
|
||||
import {NgTemplateOutlet} from './ng_template_outlet';
|
||||
import {NgStyle} from './ng_style';
|
||||
import {NgSwitch, NgSwitchWhen, NgSwitchDefault} from './ng_switch';
|
||||
import {NgPlural, NgPluralCase} from './ng_plural';
|
||||
|
@ -50,6 +51,7 @@ export const CORE_DIRECTIVES: Type[] = CONST_EXPR([
|
|||
NgClass,
|
||||
NgFor,
|
||||
NgIf,
|
||||
NgTemplateOutlet,
|
||||
NgStyle,
|
||||
NgSwitch,
|
||||
NgSwitchWhen,
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
import {Directive, Input, ViewContainerRef, ViewRef, TemplateRef} from 'angular2/core';
|
||||
import {isPresent} from 'angular2/src/facade/lang';
|
||||
|
||||
/**
|
||||
* Creates and inserts an embedded view based on a prepared `TemplateRef`.
|
||||
*
|
||||
* ### Syntax
|
||||
* - `<template [ngTemplateOutlet]="templateRefExpression"></template>`
|
||||
*/
|
||||
@Directive({selector: '[ngTemplateOutlet]'})
|
||||
export class NgTemplateOutlet {
|
||||
private _insertedViewRef: ViewRef;
|
||||
|
||||
constructor(private _viewContainerRef: ViewContainerRef) {}
|
||||
|
||||
@Input()
|
||||
set ngTemplateOutlet(templateRef: TemplateRef) {
|
||||
if (isPresent(this._insertedViewRef)) {
|
||||
this._viewContainerRef.remove(this._viewContainerRef.indexOf(this._insertedViewRef));
|
||||
}
|
||||
|
||||
if (isPresent(templateRef)) {
|
||||
this._insertedViewRef = this._viewContainerRef.createEmbeddedView(templateRef);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
import {
|
||||
AsyncTestCompleter,
|
||||
TestComponentBuilder,
|
||||
beforeEach,
|
||||
ddescribe,
|
||||
describe,
|
||||
el,
|
||||
expect,
|
||||
iit,
|
||||
inject,
|
||||
it,
|
||||
xit,
|
||||
} from 'angular2/testing_internal';
|
||||
|
||||
import {Component, Directive, TemplateRef, ContentChildren, QueryList} from 'angular2/core';
|
||||
|
||||
import {NgTemplateOutlet} from 'angular2/src/common/directives/ng_template_outlet';
|
||||
|
||||
export function main() {
|
||||
describe('insert', () => {
|
||||
it('should do nothing if templateRef is null',
|
||||
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
|
||||
var template = `<template [ngTemplateOutlet]="null"></template>`;
|
||||
tcb.overrideTemplate(TestComponent, template)
|
||||
.createAsync(TestComponent)
|
||||
.then((fixture) => {
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement).toHaveText('');
|
||||
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should insert content specified by TemplateRef',
|
||||
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
|
||||
var template =
|
||||
`<tpl-refs #refs="tplRefs"><template>foo</template></tpl-refs><template [ngTemplateOutlet]="currentTplRef"></template>`;
|
||||
tcb.overrideTemplate(TestComponent, template)
|
||||
.createAsync(TestComponent)
|
||||
.then((fixture) => {
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement).toHaveText('');
|
||||
|
||||
var refs = fixture.debugElement.children[0].getLocal('refs');
|
||||
|
||||
fixture.componentInstance.currentTplRef = refs.tplRefs.first;
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement).toHaveText('foo');
|
||||
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should clear content if TemplateRef becomes null',
|
||||
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
|
||||
var template =
|
||||
`<tpl-refs #refs="tplRefs"><template>foo</template></tpl-refs><template [ngTemplateOutlet]="currentTplRef"></template>`;
|
||||
tcb.overrideTemplate(TestComponent, template)
|
||||
.createAsync(TestComponent)
|
||||
.then((fixture) => {
|
||||
|
||||
fixture.detectChanges();
|
||||
var refs = fixture.debugElement.children[0].getLocal('refs');
|
||||
|
||||
fixture.componentInstance.currentTplRef = refs.tplRefs.first;
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement).toHaveText('foo');
|
||||
|
||||
fixture.componentInstance.currentTplRef = null;
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement).toHaveText('');
|
||||
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should swap content if TemplateRef changes',
|
||||
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
|
||||
var template = `<tpl-refs #refs="tplRefs"><template>foo</template><template>bar</template></tpl-refs><template [ngTemplateOutlet]="currentTplRef"></template>`;
|
||||
tcb.overrideTemplate(TestComponent, template)
|
||||
.createAsync(TestComponent)
|
||||
.then((fixture) => {
|
||||
|
||||
fixture.detectChanges();
|
||||
var refs = fixture.debugElement.children[0].getLocal('refs');
|
||||
|
||||
fixture.componentInstance.currentTplRef = refs.tplRefs.first;
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement).toHaveText('foo');
|
||||
|
||||
fixture.componentInstance.currentTplRef = refs.tplRefs.last;
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement).toHaveText('bar');
|
||||
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Directive({selector: 'tpl-refs', exportAs: 'tplRefs'})
|
||||
class CaptureTplRefs {
|
||||
@ContentChildren(TemplateRef) tplRefs: QueryList<TemplateRef>;
|
||||
}
|
||||
|
||||
@Component({selector: 'test-cmp', directives: [NgTemplateOutlet, CaptureTplRefs], template: ''})
|
||||
class TestComponent {
|
||||
currentTplRef: TemplateRef;
|
||||
}
|
|
@ -66,6 +66,7 @@ var NG_COMMON = [
|
|||
'NgFormControl',
|
||||
'NgFormModel',
|
||||
'NgIf',
|
||||
'NgTemplateOutlet',
|
||||
'NgModel',
|
||||
'NgSelectOption',
|
||||
'NgStyle',
|
||||
|
|
|
@ -736,6 +736,9 @@ const COMMON = [
|
|||
'NgIf',
|
||||
'NgIf.constructor(_viewContainer:ViewContainerRef, _templateRef:TemplateRef)',
|
||||
'NgIf.ngIf=(newCondition:any)',
|
||||
'NgTemplateOutlet',
|
||||
'NgTemplateOutlet.constructor(_viewContainerRef:ViewContainerRef)',
|
||||
'NgTemplateOutlet.ngTemplateOutlet=(templateRef:TemplateRef)',
|
||||
'NgLocalization',
|
||||
'NgLocalization.getPluralCategory(value:any):string',
|
||||
'NgModel',
|
||||
|
|
Loading…
Reference in New Issue