feat(NgTemplateOutlet): Make NgTemplateOutlet compatible with * syntax
BREAKING CHANGE: - Deprecate `ngOutletContext`. Use `ngTemplateOutletContext` instead
This commit is contained in:
parent
31322e73b7
commit
c0178de0e2
|
@ -15,42 +15,47 @@ import {Directive, EmbeddedViewRef, Input, OnChanges, SimpleChanges, TemplateRef
|
||||||
*
|
*
|
||||||
* @howToUse
|
* @howToUse
|
||||||
* ```
|
* ```
|
||||||
* <template [ngTemplateOutlet]="templateRefExpression"
|
* <ng-container *ngTemplateOutlet="templateRefExp; context: contextExp"></ng-container>
|
||||||
* [ngOutletContext]="objectExpression">
|
|
||||||
* </template>
|
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @description
|
* @description
|
||||||
*
|
*
|
||||||
* You can attach a context object to the `EmbeddedViewRef` by setting `[ngOutletContext]`.
|
* You can attach a context object to the `EmbeddedViewRef` by setting `[ngTemplateOutletContext]`.
|
||||||
* `[ngOutletContext]` should be an object, the object's keys will be the local template variables
|
* `[ngTemplateOutletContext]` should be an object, the object's keys will be available for binding
|
||||||
* available within the `TemplateRef`.
|
* by the local template `let` declarations.
|
||||||
*
|
*
|
||||||
* Note: using the key `$implicit` in the context object will set it's value as default.
|
* Note: using the key `$implicit` in the context object will set it's value as default.
|
||||||
*
|
*
|
||||||
|
* # Example
|
||||||
|
*
|
||||||
|
* {@example common/ngTemplateOutlet/ts/module.ts region='NgTemplateOutlet'}
|
||||||
|
*
|
||||||
* @experimental
|
* @experimental
|
||||||
*/
|
*/
|
||||||
@Directive({selector: '[ngTemplateOutlet]'})
|
@Directive({selector: '[ngTemplateOutlet]'})
|
||||||
export class NgTemplateOutlet implements OnChanges {
|
export class NgTemplateOutlet implements OnChanges {
|
||||||
private _viewRef: EmbeddedViewRef<any>;
|
private _viewRef: EmbeddedViewRef<any>;
|
||||||
private _context: Object;
|
|
||||||
private _templateRef: TemplateRef<any>;
|
@Input() public ngTemplateOutletContext: Object;
|
||||||
|
|
||||||
|
@Input() public ngTemplateOutlet: TemplateRef<any>;
|
||||||
|
|
||||||
constructor(private _viewContainerRef: ViewContainerRef) {}
|
constructor(private _viewContainerRef: ViewContainerRef) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated v4.0.0 - Renamed to ngTemplateOutletContext.
|
||||||
|
*/
|
||||||
@Input()
|
@Input()
|
||||||
set ngOutletContext(context: Object) { this._context = context; }
|
set ngOutletContext(context: Object) { this.ngTemplateOutletContext = context; }
|
||||||
|
|
||||||
@Input()
|
|
||||||
set ngTemplateOutlet(templateRef: TemplateRef<Object>) { this._templateRef = templateRef; }
|
|
||||||
|
|
||||||
ngOnChanges(changes: SimpleChanges) {
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
if (this._viewRef) {
|
if (this._viewRef) {
|
||||||
this._viewContainerRef.remove(this._viewContainerRef.indexOf(this._viewRef));
|
this._viewContainerRef.remove(this._viewContainerRef.indexOf(this._viewRef));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._templateRef) {
|
if (this.ngTemplateOutlet) {
|
||||||
this._viewRef = this._viewContainerRef.createEmbeddedView(this._templateRef, this._context);
|
this._viewRef = this._viewContainerRef.createEmbeddedView(
|
||||||
|
this.ngTemplateOutlet, this.ngTemplateOutletContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,8 +84,8 @@ export function main() {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should display template if context is null', async(() => {
|
it('should display template if context is null', async(() => {
|
||||||
const template =
|
const template = `<tpl-refs #refs="tplRefs"><template>foo</template></tpl-refs>` +
|
||||||
`<tpl-refs #refs="tplRefs"><template>foo</template></tpl-refs><template [ngTemplateOutlet]="currentTplRef" [ngOutletContext]="null"></template>`;
|
`<ng-content *ngTemplateOutlet="currentTplRef; context: null"></ng-content>`;
|
||||||
fixture = createTestComponent(template);
|
fixture = createTestComponent(template);
|
||||||
detectChangesAndExpectText('');
|
detectChangesAndExpectText('');
|
||||||
|
|
||||||
|
@ -97,7 +97,8 @@ export function main() {
|
||||||
|
|
||||||
it('should reflect initial context and changes', async(() => {
|
it('should reflect initial context and changes', async(() => {
|
||||||
const template =
|
const template =
|
||||||
`<tpl-refs #refs="tplRefs"><template let-foo="foo"><span>{{foo}}</span></template></tpl-refs><template [ngTemplateOutlet]="currentTplRef" [ngOutletContext]="context"></template>`;
|
`<tpl-refs #refs="tplRefs"><template let-foo="foo"><span>{{foo}}</span></template></tpl-refs>` +
|
||||||
|
`<ng-content *ngTemplateOutlet="currentTplRef; context: context"></ng-content>`;
|
||||||
fixture = createTestComponent(template);
|
fixture = createTestComponent(template);
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
@ -114,7 +115,8 @@ export function main() {
|
||||||
|
|
||||||
it('should reflect user defined $implicit property in the context', async(() => {
|
it('should reflect user defined $implicit property in the context', async(() => {
|
||||||
const template =
|
const template =
|
||||||
`<tpl-refs #refs="tplRefs"><template let-ctx><span>{{ctx.foo}}</span></template></tpl-refs><template [ngTemplateOutlet]="currentTplRef" [ngOutletContext]="context"></template>`;
|
`<tpl-refs #refs="tplRefs"><template let-ctx><span>{{ctx.foo}}</span></template></tpl-refs>` +
|
||||||
|
`<ng-content *ngTemplateOutlet="currentTplRef; context: context"></ng-content>`;
|
||||||
fixture = createTestComponent(template);
|
fixture = createTestComponent(template);
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
@ -128,7 +130,8 @@ export function main() {
|
||||||
|
|
||||||
it('should reflect context re-binding', async(() => {
|
it('should reflect context re-binding', async(() => {
|
||||||
const template =
|
const template =
|
||||||
`<tpl-refs #refs="tplRefs"><template let-shawshank="shawshank"><span>{{shawshank}}</span></template></tpl-refs><template [ngTemplateOutlet]="currentTplRef" [ngOutletContext]="context"></template>`;
|
`<tpl-refs #refs="tplRefs"><template let-shawshank="shawshank"><span>{{shawshank}}</span></template></tpl-refs>` +
|
||||||
|
`<ng-content *ngTemplateOutlet="currentTplRef; context: context"></ng-content>`;
|
||||||
fixture = createTestComponent(template);
|
fixture = createTestComponent(template);
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
@ -162,4 +165,4 @@ function createTestComponent(template: string): ComponentFixture<TestComponent>
|
||||||
return TestBed.overrideComponent(TestComponent, {set: {template: template}})
|
return TestBed.overrideComponent(TestComponent, {set: {template: template}})
|
||||||
.configureTestingModule({schemas: [NO_ERRORS_SCHEMA]})
|
.configureTestingModule({schemas: [NO_ERRORS_SCHEMA]})
|
||||||
.createComponent(TestComponent);
|
.createComponent(TestComponent);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {$, ExpectedConditions, browser, by, element} from 'protractor';
|
||||||
|
import {verifyNoBrowserErrors} from '../../../../_common/e2e_util';
|
||||||
|
|
||||||
|
function waitForElement(selector: string) {
|
||||||
|
const EC = ExpectedConditions;
|
||||||
|
// Waits for the element with id 'abc' to be present on the dom.
|
||||||
|
browser.wait(EC.presenceOf($(selector)), 20000);
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('ngTemplateOutlet', () => {
|
||||||
|
const URL = 'common/ngTemplateOutlet/ts/';
|
||||||
|
afterEach(verifyNoBrowserErrors);
|
||||||
|
|
||||||
|
describe('ng-template-outlet-example', () => {
|
||||||
|
it('should render', () => {
|
||||||
|
browser.get(URL);
|
||||||
|
waitForElement('ng-template-outlet-example');
|
||||||
|
expect(element.all(by.css('ng-template-outlet-example span')).getText()).toEqual([
|
||||||
|
'Hello', 'Hello World!', 'Ahoj Svet!'
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,49 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {Component, NgModule, OnInit, TemplateRef, ViewChild} from '@angular/core';
|
||||||
|
import {BrowserModule} from '@angular/platform-browser';
|
||||||
|
import {Subject} from 'rxjs/Subject';
|
||||||
|
|
||||||
|
|
||||||
|
// #docregion NgTemplateOutlet
|
||||||
|
@Component({
|
||||||
|
selector: 'ng-template-outlet-example',
|
||||||
|
template: `
|
||||||
|
<ng-container *ngTemplateOutlet="greet"></ng-container>
|
||||||
|
<hr>
|
||||||
|
<ng-container *ngTemplateOutlet="eng; context: myContext"></ng-container>
|
||||||
|
<hr>
|
||||||
|
<ng-container *ngTemplateOutlet="svk; context: myContext"></ng-container>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<template #greet><span>Hello</span></template>
|
||||||
|
<template #eng let-name><span>Hello {{name}}!</span></template>
|
||||||
|
<template #svk let-person="localSk"><span>Ahoj {{person}}!</span></template>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
class NgTemplateOutletExample {
|
||||||
|
myContext = {$implicit: 'World', localSk: 'Svet'};
|
||||||
|
}
|
||||||
|
// #enddocregion
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'example-app',
|
||||||
|
template: `<ng-template-outlet-example></ng-template-outlet-example>`
|
||||||
|
})
|
||||||
|
class ExampleApp {
|
||||||
|
}
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [BrowserModule],
|
||||||
|
declarations: [ExampleApp, NgTemplateOutletExample],
|
||||||
|
bootstrap: [ExampleApp]
|
||||||
|
})
|
||||||
|
export class AppModule {
|
||||||
|
}
|
|
@ -188,8 +188,9 @@ export declare class NgSwitchDefault {
|
||||||
|
|
||||||
/** @experimental */
|
/** @experimental */
|
||||||
export declare class NgTemplateOutlet implements OnChanges {
|
export declare class NgTemplateOutlet implements OnChanges {
|
||||||
ngOutletContext: Object;
|
/** @deprecated */ ngOutletContext: Object;
|
||||||
ngTemplateOutlet: TemplateRef<Object>;
|
ngTemplateOutlet: TemplateRef<any>;
|
||||||
|
ngTemplateOutletContext: Object;
|
||||||
constructor(_viewContainerRef: ViewContainerRef);
|
constructor(_viewContainerRef: ViewContainerRef);
|
||||||
ngOnChanges(changes: SimpleChanges): void;
|
ngOnChanges(changes: SimpleChanges): void;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue