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
|
||||
* ```
|
||||
* <template [ngTemplateOutlet]="templateRefExpression"
|
||||
* [ngOutletContext]="objectExpression">
|
||||
* </template>
|
||||
* <ng-container *ngTemplateOutlet="templateRefExp; context: contextExp"></ng-container>
|
||||
* ```
|
||||
*
|
||||
* @description
|
||||
*
|
||||
* You can attach a context object to the `EmbeddedViewRef` by setting `[ngOutletContext]`.
|
||||
* `[ngOutletContext]` should be an object, the object's keys will be the local template variables
|
||||
* available within the `TemplateRef`.
|
||||
* You can attach a context object to the `EmbeddedViewRef` by setting `[ngTemplateOutletContext]`.
|
||||
* `[ngTemplateOutletContext]` should be an object, the object's keys will be available for binding
|
||||
* by the local template `let` declarations.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
@Directive({selector: '[ngTemplateOutlet]'})
|
||||
export class NgTemplateOutlet implements OnChanges {
|
||||
private _viewRef: EmbeddedViewRef<any>;
|
||||
private _context: Object;
|
||||
private _templateRef: TemplateRef<any>;
|
||||
|
||||
@Input() public ngTemplateOutletContext: Object;
|
||||
|
||||
@Input() public ngTemplateOutlet: TemplateRef<any>;
|
||||
|
||||
constructor(private _viewContainerRef: ViewContainerRef) {}
|
||||
|
||||
/**
|
||||
* @deprecated v4.0.0 - Renamed to ngTemplateOutletContext.
|
||||
*/
|
||||
@Input()
|
||||
set ngOutletContext(context: Object) { this._context = context; }
|
||||
|
||||
@Input()
|
||||
set ngTemplateOutlet(templateRef: TemplateRef<Object>) { this._templateRef = templateRef; }
|
||||
set ngOutletContext(context: Object) { this.ngTemplateOutletContext = context; }
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
if (this._viewRef) {
|
||||
this._viewContainerRef.remove(this._viewContainerRef.indexOf(this._viewRef));
|
||||
}
|
||||
|
||||
if (this._templateRef) {
|
||||
this._viewRef = this._viewContainerRef.createEmbeddedView(this._templateRef, this._context);
|
||||
if (this.ngTemplateOutlet) {
|
||||
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(() => {
|
||||
const template =
|
||||
`<tpl-refs #refs="tplRefs"><template>foo</template></tpl-refs><template [ngTemplateOutlet]="currentTplRef" [ngOutletContext]="null"></template>`;
|
||||
const template = `<tpl-refs #refs="tplRefs"><template>foo</template></tpl-refs>` +
|
||||
`<ng-content *ngTemplateOutlet="currentTplRef; context: null"></ng-content>`;
|
||||
fixture = createTestComponent(template);
|
||||
detectChangesAndExpectText('');
|
||||
|
||||
|
@ -97,7 +97,8 @@ export function main() {
|
|||
|
||||
it('should reflect initial context and changes', async(() => {
|
||||
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.detectChanges();
|
||||
|
@ -114,7 +115,8 @@ export function main() {
|
|||
|
||||
it('should reflect user defined $implicit property in the context', async(() => {
|
||||
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.detectChanges();
|
||||
|
@ -128,7 +130,8 @@ export function main() {
|
|||
|
||||
it('should reflect context re-binding', async(() => {
|
||||
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.detectChanges();
|
||||
|
@ -162,4 +165,4 @@ function createTestComponent(template: string): ComponentFixture<TestComponent>
|
|||
return TestBed.overrideComponent(TestComponent, {set: {template: template}})
|
||||
.configureTestingModule({schemas: [NO_ERRORS_SCHEMA]})
|
||||
.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 */
|
||||
export declare class NgTemplateOutlet implements OnChanges {
|
||||
ngOutletContext: Object;
|
||||
ngTemplateOutlet: TemplateRef<Object>;
|
||||
/** @deprecated */ ngOutletContext: Object;
|
||||
ngTemplateOutlet: TemplateRef<any>;
|
||||
ngTemplateOutletContext: Object;
|
||||
constructor(_viewContainerRef: ViewContainerRef);
|
||||
ngOnChanges(changes: SimpleChanges): void;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue