parent
f816666ede
commit
743d8bc845
|
@ -783,13 +783,36 @@ export interface PipeDecorator {
|
|||
* @stable
|
||||
*/
|
||||
export interface Pipe {
|
||||
/**
|
||||
* Name of the pipe.
|
||||
*
|
||||
* The pipe name is used in template bindings. For example if a pipe is named
|
||||
* `myPipe` then it would be used in the template binding expression like
|
||||
* so: `{{ exp | myPipe }}`.
|
||||
*/
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* If Pipe is pure (its output depends only on its input.)
|
||||
*
|
||||
* Normally pipe's `translate` method is invoked on each change detection
|
||||
* cycle. If the cost of invoking the `translated` method is non-trivial and
|
||||
* if the output of the pipe depends only on its input, then declaring a pipe
|
||||
* as pure would short circuit the invocation of the `translate` method and
|
||||
* invoke the method only when the inputs to the pipe change.
|
||||
*/
|
||||
pure?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pipe decorator and metadata.
|
||||
*
|
||||
* Use the `@Pipe` annotation to declare that a given class is a pipe. A pipe
|
||||
* class must also implement {@link PipeTransform} interface.
|
||||
*
|
||||
* To use the pipe include a reference to the pipe class in
|
||||
* {@link NgModule#declarations}.
|
||||
*
|
||||
* @stable
|
||||
* @Annotation
|
||||
*/
|
||||
|
|
|
@ -7,13 +7,14 @@
|
|||
*/
|
||||
|
||||
import {SimpleChange} from '../change_detection/change_detection_util';
|
||||
import {PipeTransform} from '../change_detection/pipe_transform';
|
||||
import {OnChanges, SimpleChanges} from '../metadata/lifecycle_hooks';
|
||||
import {RendererType2} from '../render/api';
|
||||
import {Type} from '../type';
|
||||
import {resolveRendererType2} from '../view/util';
|
||||
|
||||
import {diPublic} from './di';
|
||||
import {ComponentDef, ComponentDefArgs, DirectiveDef, DirectiveDefArgs} from './interfaces/definition';
|
||||
import {ComponentDef, ComponentDefArgs, DirectiveDef, DirectiveDefArgs, PipeDef, PipeType} from './interfaces/definition';
|
||||
|
||||
|
||||
|
||||
|
@ -26,7 +27,7 @@ import {ComponentDef, ComponentDefArgs, DirectiveDef, DirectiveDefArgs} from './
|
|||
* class MyDirective {
|
||||
* // Generated by Angular Template Compiler
|
||||
* // [Symbol] syntax will not be supported by TypeScript until v2.7
|
||||
* static [COMPONENT_DEF_SYMBOL] = defineComponent({
|
||||
* static ngComponentDef = defineComponent({
|
||||
* ...
|
||||
* });
|
||||
* }
|
||||
|
@ -147,7 +148,7 @@ function invertObject(obj: any): any {
|
|||
* class MyDirective {
|
||||
* // Generated by Angular Template Compiler
|
||||
* // [Symbol] syntax will not be supported by TypeScript until v2.7
|
||||
* static [DIRECTIVE_DEF_SYMBOL] = defineDirective({
|
||||
* static ngDirectiveDef = defineDirective({
|
||||
* ...
|
||||
* });
|
||||
* }
|
||||
|
@ -155,3 +156,25 @@ function invertObject(obj: any): any {
|
|||
*/
|
||||
export const defineDirective = defineComponent as<T>(directiveDefinition: DirectiveDefArgs<T>) =>
|
||||
DirectiveDef<T>;
|
||||
|
||||
/**
|
||||
* Create a pipe definition object.
|
||||
*
|
||||
* # Example
|
||||
* ```
|
||||
* class MyPipe implements PipeTransform {
|
||||
* // Generated by Angular Template Compiler
|
||||
* static ngPipeDef = definePipe({
|
||||
* ...
|
||||
* });
|
||||
* }
|
||||
* ```
|
||||
* @param type Pipe class reference. Needed to extract pipe lifecycle hooks.
|
||||
* @param factory A factory for creating a pipe instance.
|
||||
* @param pure Whether the pipe is pure.
|
||||
*/
|
||||
export function definePipe<T>(
|
||||
{type, factory, pure}: {type: Type<T>, factory: () => PipeTransform, pure?: boolean}):
|
||||
PipeDef<T> {
|
||||
throw new Error('TODO: implement!');
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import {createComponentRef, detectChanges, getHostElement, markDirty, renderComponent} from './component';
|
||||
import {NgOnChangesFeature, PublicFeature, defineComponent, defineDirective} from './definition';
|
||||
import {NgOnChangesFeature, PublicFeature, defineComponent, defineDirective, definePipe} from './definition';
|
||||
import {InjectFlags} from './di';
|
||||
import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefFlags, DirectiveType} from './interfaces/definition';
|
||||
|
||||
|
@ -63,6 +63,15 @@ export {
|
|||
viewEnd as v,
|
||||
} from './instructions';
|
||||
|
||||
export {
|
||||
pipe as Pp,
|
||||
pipeBind1 as pb1,
|
||||
pipeBind2 as pb2,
|
||||
pipeBind3 as pb3,
|
||||
pipeBind4 as pb4,
|
||||
pipeBindV as pbV,
|
||||
} from './pipe';
|
||||
|
||||
export {
|
||||
QueryList,
|
||||
|
||||
|
@ -83,6 +92,7 @@ export {
|
|||
PublicFeature,
|
||||
defineComponent,
|
||||
defineDirective,
|
||||
definePipe,
|
||||
};
|
||||
export {createComponentRef, detectChanges, getHostElement, markDirty, renderComponent};
|
||||
export {CssSelector} from './interfaces/projection';
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {PipeTransform} from '../../change_detection/pipe_transform';
|
||||
import {RendererType2} from '../../render/api';
|
||||
import {Type} from '../../type';
|
||||
import {resolveRendererType2} from '../../view/util';
|
||||
|
@ -23,6 +24,8 @@ export interface DirectiveType<T> extends Type<T> { ngDirectiveDef: DirectiveDef
|
|||
|
||||
export const enum DirectiveDefFlags {ContentQuery = 0b10}
|
||||
|
||||
export interface PipeType<T> extends Type<T> { ngPipeDef: PipeDef<T>; }
|
||||
|
||||
/**
|
||||
* `DirectiveDef` is a compiled version of the Directive used by the renderer instructions.
|
||||
*/
|
||||
|
@ -109,6 +112,31 @@ export interface ComponentDef<T> extends DirectiveDef<T> {
|
|||
readonly rendererType: RendererType2|null;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export interface PipeDef<T> {
|
||||
/**
|
||||
* factory function used to create a new directive instance.
|
||||
*
|
||||
* NOTE: this property is short (1 char) because it is used in
|
||||
* component templates which is sensitive to size.
|
||||
*/
|
||||
n: () => PipeTransform;
|
||||
|
||||
/**
|
||||
* Whether or not the pipe is pure.
|
||||
*
|
||||
* Pure pipes result only depends on the pipe input and not on internal
|
||||
* state of the pipe.
|
||||
*/
|
||||
pure: boolean;
|
||||
|
||||
/* The following are lifecycle hooks for this pipe */
|
||||
onDestroy: (() => void)|null;
|
||||
}
|
||||
|
||||
|
||||
export interface DirectiveDefArgs<T> {
|
||||
type: Type<T>;
|
||||
factory: () => T | [T];
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
/**
|
||||
* @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 {PipeDef} from './interfaces/definition';
|
||||
|
||||
/**
|
||||
* Create a pipe.
|
||||
*
|
||||
* @param index Pipe index where the pipe will be stored.
|
||||
* @param pipeDef Pipe definition object for registering life cycle hooks.
|
||||
* @param pipe A Pipe instance.
|
||||
*/
|
||||
export function pipe<T>(index: number, pipeDef: PipeDef<T>, pipe: T): void {
|
||||
throw new Error('TODO: implement!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes a pure pipe with 4 arguments.
|
||||
*
|
||||
* This instruction acts as a guard to {@link PipeTransform#transform} invoking
|
||||
* the pipe only when an input to the pipe changes.
|
||||
*
|
||||
* @param index Pipe index where the pipe was stored on creation.
|
||||
* @param v1 1st argument to {@link PipeTransform#transform}.
|
||||
*/
|
||||
export function pipeBind1(index: number, v1: any): any {
|
||||
throw new Error('TODO: implement!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes a pure pipe with 4 arguments.
|
||||
*
|
||||
* This instruction acts as a guard to {@link PipeTransform#transform} invoking
|
||||
* the pipe only when an input to the pipe changes.
|
||||
*
|
||||
* @param index Pipe index where the pipe was stored on creation.
|
||||
* @param v1 1st argument to {@link PipeTransform#transform}.
|
||||
* @param v2 2nd argument to {@link PipeTransform#transform}.
|
||||
*/
|
||||
export function pipeBind2(index: number, v1: any, v2: any): any {
|
||||
throw new Error('TODO: implement!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes a pure pipe with 4 arguments.
|
||||
*
|
||||
* This instruction acts as a guard to {@link PipeTransform#transform} invoking
|
||||
* the pipe only when an input to the pipe changes.
|
||||
*
|
||||
* @param index Pipe index where the pipe was stored on creation.
|
||||
* @param v1 1st argument to {@link PipeTransform#transform}.
|
||||
* @param v2 2nd argument to {@link PipeTransform#transform}.
|
||||
* @param v3 4rd argument to {@link PipeTransform#transform}.
|
||||
*/
|
||||
export function pipeBind3(index: number, v1: any, v2: any, v3: any): any {
|
||||
throw new Error('TODO: implement!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes a pure pipe with 4 arguments.
|
||||
*
|
||||
* This instruction acts as a guard to {@link PipeTransform#transform} invoking
|
||||
* the pipe only when an input to the pipe changes.
|
||||
*
|
||||
* @param index Pipe index where the pipe was stored on creation.
|
||||
* @param v1 1st argument to {@link PipeTransform#transform}.
|
||||
* @param v2 2nd argument to {@link PipeTransform#transform}.
|
||||
* @param v3 3rd argument to {@link PipeTransform#transform}.
|
||||
* @param v4 4th argument to {@link PipeTransform#transform}.
|
||||
*/
|
||||
export function pipeBind4(index: number, v1: any, v2: any, v3: any, v4: any): any {
|
||||
throw new Error('TODO: implement!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes a pure pipe with variable number of arguments.
|
||||
*
|
||||
* This instruction acts as a guard to {@link PipeTransform#transform} invoking
|
||||
* the pipe only when an input to the pipe changes.
|
||||
*
|
||||
* @param index Pipe index where the pipe was stored on creation.
|
||||
* @param values Array of arguments to pass to {@link PipeTransform#transform} method.
|
||||
*/
|
||||
export function pipeBindV(index: number, values: any[]): any {
|
||||
throw new Error('TODO: implement!');
|
||||
}
|
|
@ -6,7 +6,7 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Component, ContentChild, Directive, Injectable, Input, NgModule, Optional, QueryList, SimpleChanges, TemplateRef, Type, ViewChild, ViewContainerRef} from '../../src/core';
|
||||
import {Component, ContentChild, Directive, Injectable, Input, NgModule, OnDestroy, Optional, Pipe, PipeTransform, QueryList, SimpleChanges, TemplateRef, Type, ViewChild, ViewContainerRef} from '../../src/core';
|
||||
import * as r3 from '../../src/render3/index';
|
||||
|
||||
import {containerEl, renderComponent, requestAnimationFrame, toHtml} from './render_util';
|
||||
|
@ -369,6 +369,69 @@ describe('compiler specification', () => {
|
|||
|
||||
});
|
||||
|
||||
xdescribe('pipes', () => {
|
||||
@Pipe({
|
||||
name: 'myPipe',
|
||||
})
|
||||
class MyPipe implements PipeTransform,
|
||||
OnDestroy {
|
||||
transform(value: any, ...args: any[]) { throw new Error('Method not implemented.'); }
|
||||
ngOnDestroy(): void { throw new Error('Method not implemented.'); }
|
||||
|
||||
// NORMATIVE
|
||||
static ngPipeDef = r3.definePipe(
|
||||
{type: MyPipe, factory: function MyPipe_Factory() { return new MyPipe(); }});
|
||||
// /NORMATIVE
|
||||
}
|
||||
|
||||
@Pipe({
|
||||
name: 'myPurePipe',
|
||||
pure: true,
|
||||
})
|
||||
class MyPurePipe implements PipeTransform {
|
||||
transform(value: any, ...args: any[]) { throw new Error('Method not implemented.'); }
|
||||
|
||||
// NORMATIVE
|
||||
static ngPipeDef = r3.definePipe({
|
||||
type: MyPurePipe,
|
||||
factory: function MyPurePipe_Factory() { return new MyPurePipe(); },
|
||||
pure: true
|
||||
});
|
||||
// /NORMATIVE
|
||||
}
|
||||
|
||||
@Component({template: `{{name | myPipe:size | myPurePipe:size }}`})
|
||||
class MyApp {
|
||||
name = 'World';
|
||||
size = 0;
|
||||
|
||||
// NORMATIVE
|
||||
static ngComponentDef = r3.defineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
factory: function MyApp_Factory() { return new MyApp(); },
|
||||
template: function MyApp_Template(ctx: MyApp, cm: boolean) {
|
||||
if (cm) {
|
||||
r3.Pp(0, MyPipe_ngPipeDef, MyPipe_ngPipeDef.n());
|
||||
r3.Pp(1, MyPurePipe_ngPipeDef, MyPurePipe_ngPipeDef.n());
|
||||
r3.T(2);
|
||||
}
|
||||
r3.t(
|
||||
2, r3.b1('', r3.pb2(1, r3.m<MyPipe>(0).transform(ctx.name, ctx.size), ctx.size), ''));
|
||||
}
|
||||
});
|
||||
// /NORMATIVE
|
||||
}
|
||||
// NORMATIVE
|
||||
const MyPipe_ngPipeDef = MyPipe.ngPipeDef;
|
||||
const MyPurePipe_ngPipeDef = MyPurePipe.ngPipeDef;
|
||||
// /NORMATIVE
|
||||
|
||||
it('should render pipes', () => {
|
||||
// TODO(misko): write a test once pipes runtime is implemented.
|
||||
});
|
||||
});
|
||||
|
||||
describe('local references', () => {
|
||||
// TODO(misko): currently disabled until local refs are working
|
||||
xit('should translate DOM structure', () => {
|
||||
|
|
Loading…
Reference in New Issue