Skip to content

Commit

Permalink
feat(pipe): added the Pipe decorator and the pipe property to View
Browse files Browse the repository at this point in the history
BREAKING CHANGE:
    Instead of configuring pipes via a Pipes object, now you can configure them by providing the pipes property to the View decorator.

    @pipe({
      name: 'double'
    })
    class DoublePipe {
      transform(value, args) { return value * 2; }
    }

    @view({
      template: '{{ 10 | double}}'
      pipes: [DoublePipe]
    })
    class CustomComponent {}

Closes #3572
  • Loading branch information
vsavkin committed Aug 12, 2015
1 parent 02b7e61 commit 5b5d31f
Show file tree
Hide file tree
Showing 62 changed files with 623 additions and 520 deletions.
5 changes: 4 additions & 1 deletion modules/angular2/annotations.ts
Expand Up @@ -12,6 +12,7 @@
export {
ComponentAnnotation,
DirectiveAnnotation,
PipeAnnotation,
LifecycleEvent
} from './src/core/annotations/annotations';

Expand Down Expand Up @@ -43,5 +44,7 @@ export {
ViewFactory,
Query,
QueryFactory,
ViewQuery
ViewQuery,
Pipe,
PipeFactory
} from 'angular2/src/core/annotations/decorators';
6 changes: 2 additions & 4 deletions modules/angular2/change_detection.ts
Expand Up @@ -20,14 +20,12 @@ export {
ChangeDetectorRef,

WrappedValue,
defaultPipes,
Pipe,
Pipes,
PipeTransform,
IterableDiffers,
IterableDiffer,
IterableDifferFactory,
KeyValueDiffers,
KeyValueDiffer,
KeyValueDifferFactory,
BasePipe
BasePipeTransform
} from 'angular2/src/change_detection/change_detection';
15 changes: 8 additions & 7 deletions modules/angular2/pipes.ts
Expand Up @@ -4,10 +4,11 @@
* This module provides advanced support for extending change detection.
*/

export {UpperCasePipe} from './src/change_detection/pipes/uppercase_pipe';
export {LowerCasePipe} from './src/change_detection/pipes/lowercase_pipe';
export {AsyncPipe} from './src/change_detection/pipes/async_pipe';
export {JsonPipe} from './src/change_detection/pipes/json_pipe';
export {DatePipe} from './src/change_detection/pipes/date_pipe';
export {DecimalPipe, PercentPipe, CurrencyPipe} from './src/change_detection/pipes/number_pipe';
export {LimitToPipe} from './src/change_detection/pipes/limit_to_pipe';
export {UpperCasePipe} from './src/pipes/uppercase_pipe';
export {LowerCasePipe} from './src/pipes/lowercase_pipe';
export {AsyncPipe} from './src/pipes/async_pipe';
export {JsonPipe} from './src/pipes/json_pipe';
export {DatePipe} from './src/pipes/date_pipe';
export {DecimalPipe, PercentPipe, CurrencyPipe} from './src/pipes/number_pipe';
export {LimitToPipe} from './src/pipes/limit_to_pipe';
export {DEFAULT_PIPES_TOKEN, DEFAULT_PIPES} from './src/pipes/default_pipes';
Expand Up @@ -4,6 +4,7 @@ import {ChangeDetectionUtil} from './change_detection_util';
import {ChangeDetectorRef} from './change_detector_ref';
import {DirectiveRecord} from './directive_record';
import {ChangeDetector, ChangeDispatcher} from './interfaces';
import {Pipes} from './pipes';
import {
ChangeDetectionError,
ExpressionChangedAfterItHasBeenCheckedException,
Expand All @@ -12,7 +13,6 @@ import {
import {ProtoRecord} from './proto_record';
import {BindingRecord} from './binding_record';
import {Locals} from './parser/locals';
import {Pipes} from './pipes/pipes';
import {CHECK_ALWAYS, CHECK_ONCE, CHECKED, DETACHED, ON_PUSH} from './constants';
import {wtfCreateScope, wtfLeave, WtfScopeFn} from '../profile/profile';

Expand Down
32 changes: 2 additions & 30 deletions modules/angular2/src/change_detection/change_detection.ts
@@ -1,18 +1,10 @@
import {JitProtoChangeDetector} from './jit_proto_change_detector';
import {PregenProtoChangeDetector} from './pregen_proto_change_detector';
import {DynamicProtoChangeDetector} from './proto_change_detector';
import {Pipes} from './pipes/pipes';
import {IterableDiffers, IterableDifferFactory} from './differs/iterable_differs';
import {DefaultIterableDifferFactory} from './differs/default_iterable_differ';
import {KeyValueDiffers, KeyValueDifferFactory} from './differs/keyvalue_differs';
import {DefaultKeyValueDifferFactory} from './differs/default_keyvalue_differ';
import {AsyncPipe} from './pipes/async_pipe';
import {UpperCasePipe} from './pipes/uppercase_pipe';
import {LowerCasePipe} from './pipes/lowercase_pipe';
import {JsonPipe} from './pipes/json_pipe';
import {LimitToPipe} from './pipes/limit_to_pipe';
import {DatePipe} from './pipes/date_pipe';
import {DecimalPipe, PercentPipe, CurrencyPipe} from './pipes/number_pipe';
import {ChangeDetection, ProtoChangeDetector, ChangeDetectorDefinition} from './interfaces';
import {Injector, Inject, Injectable, OpaqueToken, Optional, Binding} from 'angular2/di';
import {List, StringMap, StringMapWrapper} from 'angular2/src/facade/collection';
Expand Down Expand Up @@ -50,30 +42,10 @@ export {BindingRecord} from './binding_record';
export {DirectiveIndex, DirectiveRecord} from './directive_record';
export {DynamicChangeDetector} from './dynamic_change_detector';
export {ChangeDetectorRef} from './change_detector_ref';
export {Pipes} from './pipes/pipes';
export {IterableDiffers, IterableDiffer, IterableDifferFactory} from './differs/iterable_differs';
export {KeyValueDiffers, KeyValueDiffer, KeyValueDifferFactory} from './differs/keyvalue_differs';
export {WrappedValue, Pipe, BasePipe} from './pipes/pipe';


function createPipes(inj: Injector): Pipes {
return new Pipes(
{
"async": AsyncPipe,
"uppercase": UpperCasePipe,
"lowercase": LowerCasePipe,
"json": JsonPipe,
"limitTo": LimitToPipe,
"number": DecimalPipe,
"percent": PercentPipe,
"currency": CurrencyPipe,
"date": DatePipe
},
inj);
}

export const defaultPipes: Binding =
CONST_EXPR(new Binding(Pipes, {toFactory: createPipes, deps: [Injector]}));
export {PipeTransform, BasePipeTransform} from './pipe_transform';
export {WrappedValue} from './change_detection_util';

/**
* Structural diffing for `Object`s and `Map`s.
Expand Down
Expand Up @@ -179,12 +179,10 @@ export class ChangeDetectorJITGenerator {
var newValue = this._names.getLocalName(r.selfIndex);

var pipe = this._names.getPipeName(r.selfIndex);
var cdRef = "this.ref";
var pipeType = r.name;

var read = `
if (${pipe} === ${UTIL}.uninitialized) {
${pipe} = ${this._names.getPipesAccessorName()}.get('${pipeType}', ${cdRef});
${pipe} = ${this._names.getPipesAccessorName()}.get('${pipeType}');
}
${newValue} = ${pipe}.transform(${context}, [${argString}]);
`;
Expand Down
40 changes: 39 additions & 1 deletion modules/angular2/src/change_detection/change_detection_util.ts
@@ -1,9 +1,47 @@
import {CONST_EXPR, isPresent, isBlank, BaseException, Type} from 'angular2/src/facade/lang';
import {List, ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
import {ProtoRecord} from './proto_record';
import {WrappedValue} from './pipes/pipe';
import {CHECK_ALWAYS, CHECK_ONCE, CHECKED, DETACHED, ON_PUSH} from './constants';


/**
* Indicates that the result of a {@link Pipe} transformation has changed even though the reference
* has not changed.
*
* The wrapped value will be unwrapped by change detection, and the unwrapped value will be stored.
*
* Example:
*
* ```
* if (this._latestValue === this._latestReturnedValue) {
* return this._latestReturnedValue;
* } else {
* this._latestReturnedValue = this._latestValue;
* return WrappedValue.wrap(this._latestValue); // this will force update
* }
* ```
*/
export class WrappedValue {
constructor(public wrapped: any) {}

static wrap(value: any): WrappedValue {
var w = _wrappedValues[_wrappedIndex++ % 5];
w.wrapped = value;
return w;
}
}

var _wrappedValues = [
new WrappedValue(null),
new WrappedValue(null),
new WrappedValue(null),
new WrappedValue(null),
new WrappedValue(null)
];

var _wrappedIndex = 0;


export class SimpleChange {
constructor(public previousValue: any, public currentValue: any) {}

Expand Down
Expand Up @@ -269,7 +269,7 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
var storedPipe = this._readPipe(proto);
if (isPresent(storedPipe)) return storedPipe;

var pipe = this.pipes.get(proto.name, this.ref);
var pipe = this.pipes.get(proto.name);
this._writePipe(proto, pipe);
return pipe;
}
Expand Down
45 changes: 45 additions & 0 deletions modules/angular2/src/change_detection/pipe_transform.ts
@@ -0,0 +1,45 @@
import {ABSTRACT, BaseException, CONST, Type} from 'angular2/src/facade/lang';

/**
* An interface which all pipes must implement.
*
* #Example
*
* ```
* class DoublePipe implements PipeTransform {
* onDestroy() {}
*
* transform(value, args = []) {
* return `${value}${value}`;
* }
* }
* ```
*/
export interface PipeTransform {
onDestroy(): void;

transform(value: any, args: List<any>): any;
}

/**
* Provides default implementation of the `onDestroy` method.
*
* #Example
*
* ```
* class DoublePipe extends BasePipe {
* transform(value) {
* return `${value}${value}`;
* }
* }
* ```
*/
@CONST()
export class BasePipeTransform implements PipeTransform {
onDestroy(): void {}
transform(value: any, args: List<any>): any { return _abstract(); }
}

function _abstract() {
throw new BaseException('This method is abstract');
}
3 changes: 3 additions & 0 deletions modules/angular2/src/change_detection/pipes.ts
@@ -0,0 +1,3 @@
import {PipeTransform} from './pipe_transform';

export interface Pipes { get(name: string): PipeTransform; }
84 changes: 0 additions & 84 deletions modules/angular2/src/change_detection/pipes/pipe.ts

This file was deleted.

0 comments on commit 5b5d31f

Please sign in to comment.