parent
f816666ede
commit
743d8bc845
@ -783,13 +783,36 @@ export interface PipeDecorator {
|
|||||||
* @stable
|
* @stable
|
||||||
*/
|
*/
|
||||||
export interface Pipe {
|
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;
|
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;
|
pure?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pipe decorator and metadata.
|
* 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
|
* @stable
|
||||||
* @Annotation
|
* @Annotation
|
||||||
*/
|
*/
|
||||||
|
@ -7,13 +7,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {SimpleChange} from '../change_detection/change_detection_util';
|
import {SimpleChange} from '../change_detection/change_detection_util';
|
||||||
|
import {PipeTransform} from '../change_detection/pipe_transform';
|
||||||
import {OnChanges, SimpleChanges} from '../metadata/lifecycle_hooks';
|
import {OnChanges, SimpleChanges} from '../metadata/lifecycle_hooks';
|
||||||
import {RendererType2} from '../render/api';
|
import {RendererType2} from '../render/api';
|
||||||
import {Type} from '../type';
|
import {Type} from '../type';
|
||||||
import {resolveRendererType2} from '../view/util';
|
import {resolveRendererType2} from '../view/util';
|
||||||
|
|
||||||
import {diPublic} from './di';
|
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 {
|
* class MyDirective {
|
||||||
* // Generated by Angular Template Compiler
|
* // Generated by Angular Template Compiler
|
||||||
* // [Symbol] syntax will not be supported by TypeScript until v2.7
|
* // [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 {
|
* class MyDirective {
|
||||||
* // Generated by Angular Template Compiler
|
* // Generated by Angular Template Compiler
|
||||||
* // [Symbol] syntax will not be supported by TypeScript until v2.7
|
* // [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>) =>
|
export const defineDirective = defineComponent as<T>(directiveDefinition: DirectiveDefArgs<T>) =>
|
||||||
DirectiveDef<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 {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 {InjectFlags} from './di';
|
||||||
import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefFlags, DirectiveType} from './interfaces/definition';
|
import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefFlags, DirectiveType} from './interfaces/definition';
|
||||||
|
|
||||||
@ -63,6 +63,15 @@ export {
|
|||||||
viewEnd as v,
|
viewEnd as v,
|
||||||
} from './instructions';
|
} from './instructions';
|
||||||
|
|
||||||
|
export {
|
||||||
|
pipe as Pp,
|
||||||
|
pipeBind1 as pb1,
|
||||||
|
pipeBind2 as pb2,
|
||||||
|
pipeBind3 as pb3,
|
||||||
|
pipeBind4 as pb4,
|
||||||
|
pipeBindV as pbV,
|
||||||
|
} from './pipe';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
QueryList,
|
QueryList,
|
||||||
|
|
||||||
@ -83,6 +92,7 @@ export {
|
|||||||
PublicFeature,
|
PublicFeature,
|
||||||
defineComponent,
|
defineComponent,
|
||||||
defineDirective,
|
defineDirective,
|
||||||
|
definePipe,
|
||||||
};
|
};
|
||||||
export {createComponentRef, detectChanges, getHostElement, markDirty, renderComponent};
|
export {createComponentRef, detectChanges, getHostElement, markDirty, renderComponent};
|
||||||
export {CssSelector} from './interfaces/projection';
|
export {CssSelector} from './interfaces/projection';
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import {PipeTransform} from '../../change_detection/pipe_transform';
|
||||||
import {RendererType2} from '../../render/api';
|
import {RendererType2} from '../../render/api';
|
||||||
import {Type} from '../../type';
|
import {Type} from '../../type';
|
||||||
import {resolveRendererType2} from '../../view/util';
|
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 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.
|
* `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;
|
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> {
|
export interface DirectiveDefArgs<T> {
|
||||||
type: Type<T>;
|
type: Type<T>;
|
||||||
factory: () => T | [T];
|
factory: () => T | [T];
|
||||||
|
91
packages/core/src/render3/pipe.ts
Normal file
91
packages/core/src/render3/pipe.ts
Normal file
@ -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
|
* 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 * as r3 from '../../src/render3/index';
|
||||||
|
|
||||||
import {containerEl, renderComponent, requestAnimationFrame, toHtml} from './render_util';
|
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', () => {
|
describe('local references', () => {
|
||||||
// TODO(misko): currently disabled until local refs are working
|
// TODO(misko): currently disabled until local refs are working
|
||||||
xit('should translate DOM structure', () => {
|
xit('should translate DOM structure', () => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user