refactor(pipes): use Injector instead of pipe factories for pipe instantiation
BREAKING CHANGE - Pipe factories have been removed. - PIpe names to pipe implementations are 1-to-1 instead of 1-to-* Before: class DateFormatter { transform(date, args){} } class DateFormatterFactory { supporst(obj) { return true; } create(cdRef) { return new DateFormatter(); } } new Pipes({date: [new DateFormatterFactory()]}) After class DateFormatter { transform(date, args){} } new Pipes({date: DateFormatter})
This commit is contained in:
parent
06da60f4b7
commit
2dcf714d2b
|
@ -29,8 +29,5 @@ export {
|
||||||
KeyValueDiffers,
|
KeyValueDiffers,
|
||||||
KeyValueDiffer,
|
KeyValueDiffer,
|
||||||
KeyValueDifferFactory,
|
KeyValueDifferFactory,
|
||||||
PipeFactory,
|
BasePipe
|
||||||
BasePipe,
|
|
||||||
NullPipe,
|
|
||||||
NullPipeFactory
|
|
||||||
} from 'angular2/src/change_detection/change_detection';
|
} from 'angular2/src/change_detection/change_detection';
|
||||||
|
|
|
@ -1,22 +1,20 @@
|
||||||
import {JitProtoChangeDetector} from './jit_proto_change_detector';
|
import {JitProtoChangeDetector} from './jit_proto_change_detector';
|
||||||
import {PregenProtoChangeDetector} from './pregen_proto_change_detector';
|
import {PregenProtoChangeDetector} from './pregen_proto_change_detector';
|
||||||
import {DynamicProtoChangeDetector} from './proto_change_detector';
|
import {DynamicProtoChangeDetector} from './proto_change_detector';
|
||||||
import {PipeFactory, Pipe} from './pipes/pipe';
|
|
||||||
import {Pipes} from './pipes/pipes';
|
import {Pipes} from './pipes/pipes';
|
||||||
import {IterableDiffers, IterableDifferFactory} from './differs/iterable_differs';
|
import {IterableDiffers, IterableDifferFactory} from './differs/iterable_differs';
|
||||||
import {DefaultIterableDifferFactory} from './differs/default_iterable_differ';
|
import {DefaultIterableDifferFactory} from './differs/default_iterable_differ';
|
||||||
import {KeyValueDiffers, KeyValueDifferFactory} from './differs/keyvalue_differs';
|
import {KeyValueDiffers, KeyValueDifferFactory} from './differs/keyvalue_differs';
|
||||||
import {DefaultKeyValueDifferFactory} from './differs/default_keyvalue_differ';
|
import {DefaultKeyValueDifferFactory} from './differs/default_keyvalue_differ';
|
||||||
import {AsyncPipeFactory} from './pipes/async_pipe';
|
import {AsyncPipe} from './pipes/async_pipe';
|
||||||
import {UpperCasePipe} from './pipes/uppercase_pipe';
|
import {UpperCasePipe} from './pipes/uppercase_pipe';
|
||||||
import {LowerCasePipe} from './pipes/lowercase_pipe';
|
import {LowerCasePipe} from './pipes/lowercase_pipe';
|
||||||
import {JsonPipe} from './pipes/json_pipe';
|
import {JsonPipe} from './pipes/json_pipe';
|
||||||
import {LimitToPipeFactory} from './pipes/limit_to_pipe';
|
import {LimitToPipe} from './pipes/limit_to_pipe';
|
||||||
import {DatePipe} from './pipes/date_pipe';
|
import {DatePipe} from './pipes/date_pipe';
|
||||||
import {DecimalPipe, PercentPipe, CurrencyPipe} from './pipes/number_pipe';
|
import {DecimalPipe, PercentPipe, CurrencyPipe} from './pipes/number_pipe';
|
||||||
import {NullPipeFactory} from './pipes/null_pipe';
|
|
||||||
import {ChangeDetection, ProtoChangeDetector, ChangeDetectorDefinition} from './interfaces';
|
import {ChangeDetection, ProtoChangeDetector, ChangeDetectorDefinition} from './interfaces';
|
||||||
import {Inject, Injectable, OpaqueToken, Optional} from 'angular2/di';
|
import {Injector, Inject, Injectable, OpaqueToken, Optional, Binding} from 'angular2/di';
|
||||||
import {List, StringMap, StringMapWrapper} from 'angular2/src/facade/collection';
|
import {List, StringMap, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||||
import {CONST, CONST_EXPR, isPresent, BaseException} from 'angular2/src/facade/lang';
|
import {CONST, CONST_EXPR, isPresent, BaseException} from 'angular2/src/facade/lang';
|
||||||
|
|
||||||
|
@ -55,10 +53,28 @@ export {ChangeDetectorRef} from './change_detector_ref';
|
||||||
export {Pipes} from './pipes/pipes';
|
export {Pipes} from './pipes/pipes';
|
||||||
export {IterableDiffers, IterableDiffer, IterableDifferFactory} from './differs/iterable_differs';
|
export {IterableDiffers, IterableDiffer, IterableDifferFactory} from './differs/iterable_differs';
|
||||||
export {KeyValueDiffers, KeyValueDiffer, KeyValueDifferFactory} from './differs/keyvalue_differs';
|
export {KeyValueDiffers, KeyValueDiffer, KeyValueDifferFactory} from './differs/keyvalue_differs';
|
||||||
export {WrappedValue, Pipe, PipeFactory, BasePipe} from './pipes/pipe';
|
export {WrappedValue, Pipe, BasePipe} from './pipes/pipe';
|
||||||
export {NullPipe, NullPipeFactory} from './pipes/null_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]}));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Structural diffing for `Object`s and `Map`s.
|
* Structural diffing for `Object`s and `Map`s.
|
||||||
*/
|
*/
|
||||||
|
@ -71,73 +87,6 @@ export const keyValDiff: KeyValueDifferFactory[] =
|
||||||
export const iterableDiff: IterableDifferFactory[] =
|
export const iterableDiff: IterableDifferFactory[] =
|
||||||
CONST_EXPR([CONST_EXPR(new DefaultIterableDifferFactory())]);
|
CONST_EXPR([CONST_EXPR(new DefaultIterableDifferFactory())]);
|
||||||
|
|
||||||
/**
|
|
||||||
* Async binding to such types as Observable.
|
|
||||||
*/
|
|
||||||
export const async: List<PipeFactory> =
|
|
||||||
CONST_EXPR([CONST_EXPR(new AsyncPipeFactory()), CONST_EXPR(new NullPipeFactory())]);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uppercase text transform.
|
|
||||||
*/
|
|
||||||
export const uppercase: List<PipeFactory> =
|
|
||||||
CONST_EXPR([CONST_EXPR(new UpperCasePipe()), CONST_EXPR(new NullPipeFactory())]);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Lowercase text transform.
|
|
||||||
*/
|
|
||||||
export const lowercase: List<PipeFactory> =
|
|
||||||
CONST_EXPR([CONST_EXPR(new LowerCasePipe()), CONST_EXPR(new NullPipeFactory())]);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Json stringify transform.
|
|
||||||
*/
|
|
||||||
export const json: List<PipeFactory> =
|
|
||||||
CONST_EXPR([CONST_EXPR(new JsonPipe()), CONST_EXPR(new NullPipeFactory())]);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* LimitTo text transform.
|
|
||||||
*/
|
|
||||||
export const limitTo: List<PipeFactory> =
|
|
||||||
CONST_EXPR([CONST_EXPR(new LimitToPipeFactory()), CONST_EXPR(new NullPipeFactory())]);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Number number transform.
|
|
||||||
*/
|
|
||||||
export const decimal: List<PipeFactory> =
|
|
||||||
CONST_EXPR([CONST_EXPR(new DecimalPipe()), CONST_EXPR(new NullPipeFactory())]);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Percent number transform.
|
|
||||||
*/
|
|
||||||
export const percent: List<PipeFactory> =
|
|
||||||
CONST_EXPR([CONST_EXPR(new PercentPipe()), CONST_EXPR(new NullPipeFactory())]);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Currency number transform.
|
|
||||||
*/
|
|
||||||
export const currency: List<PipeFactory> =
|
|
||||||
CONST_EXPR([CONST_EXPR(new CurrencyPipe()), CONST_EXPR(new NullPipeFactory())]);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Date/time formatter.
|
|
||||||
*/
|
|
||||||
export const date: List<PipeFactory> =
|
|
||||||
CONST_EXPR([CONST_EXPR(new DatePipe()), CONST_EXPR(new NullPipeFactory())]);
|
|
||||||
|
|
||||||
|
|
||||||
export const defaultPipes: Pipes = CONST_EXPR(new Pipes({
|
|
||||||
"async": async,
|
|
||||||
"uppercase": uppercase,
|
|
||||||
"lowercase": lowercase,
|
|
||||||
"json": json,
|
|
||||||
"limitTo": limitTo,
|
|
||||||
"number": decimal,
|
|
||||||
"percent": percent,
|
|
||||||
"currency": currency,
|
|
||||||
"date": date
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const defaultIterableDiffers = CONST_EXPR(new IterableDiffers(iterableDiff));
|
export const defaultIterableDiffers = CONST_EXPR(new IterableDiffers(iterableDiff));
|
||||||
|
|
||||||
export const defaultKeyValueDiffers = CONST_EXPR(new KeyValueDiffers(keyValDiff));
|
export const defaultKeyValueDiffers = CONST_EXPR(new KeyValueDiffers(keyValDiff));
|
||||||
|
|
|
@ -184,10 +184,7 @@ export class ChangeDetectorJITGenerator {
|
||||||
|
|
||||||
var read = `
|
var read = `
|
||||||
if (${pipe} === ${UTIL}.uninitialized) {
|
if (${pipe} === ${UTIL}.uninitialized) {
|
||||||
${pipe} = ${this._names.getPipesAccessorName()}.get('${pipeType}', ${context}, ${cdRef});
|
${pipe} = ${this._names.getPipesAccessorName()}.get('${pipeType}', ${cdRef});
|
||||||
} else if (!${pipe}.supports(${context})) {
|
|
||||||
${pipe}.onDestroy();
|
|
||||||
${pipe} = ${this._names.getPipesAccessorName()}.get('${pipeType}', ${context}, ${cdRef});
|
|
||||||
}
|
}
|
||||||
${newValue} = ${pipe}.transform(${context}, [${argString}]);
|
${newValue} = ${pipe}.transform(${context}, [${argString}]);
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -267,13 +267,9 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
|
||||||
|
|
||||||
_pipeFor(proto: ProtoRecord, context) {
|
_pipeFor(proto: ProtoRecord, context) {
|
||||||
var storedPipe = this._readPipe(proto);
|
var storedPipe = this._readPipe(proto);
|
||||||
if (isPresent(storedPipe) && storedPipe.supports(context)) {
|
if (isPresent(storedPipe)) return storedPipe;
|
||||||
return storedPipe;
|
|
||||||
}
|
var pipe = this.pipes.get(proto.name, this.ref);
|
||||||
if (isPresent(storedPipe)) {
|
|
||||||
storedPipe.onDestroy();
|
|
||||||
}
|
|
||||||
var pipe = this.pipes.get(proto.name, context, this.ref);
|
|
||||||
this._writePipe(proto, pipe);
|
this._writePipe(proto, pipe);
|
||||||
return pipe;
|
return pipe;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import {isBlank, isPresent, isPromise, CONST, BaseException} from 'angular2/src/facade/lang';
|
import {isBlank, isPresent, isPromise, CONST, BaseException} from 'angular2/src/facade/lang';
|
||||||
import {Observable, Promise, ObservableWrapper} from 'angular2/src/facade/async';
|
import {Observable, Promise, ObservableWrapper} from 'angular2/src/facade/async';
|
||||||
import {Pipe, WrappedValue, PipeFactory} from './pipe';
|
import {Injectable} from 'angular2/di';
|
||||||
|
import {Pipe, WrappedValue, InvalidPipeArgumentException} from './pipe';
|
||||||
import {ChangeDetectorRef} from '../change_detector_ref';
|
import {ChangeDetectorRef} from '../change_detector_ref';
|
||||||
|
|
||||||
|
|
||||||
|
@ -52,6 +53,7 @@ var _observableStrategy = new ObservableStrategy();
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
|
@Injectable()
|
||||||
export class AsyncPipe implements Pipe {
|
export class AsyncPipe implements Pipe {
|
||||||
_latestValue: Object = null;
|
_latestValue: Object = null;
|
||||||
_latestReturnedValue: Object = null;
|
_latestReturnedValue: Object = null;
|
||||||
|
@ -62,8 +64,6 @@ export class AsyncPipe implements Pipe {
|
||||||
|
|
||||||
constructor(public _ref: ChangeDetectorRef) {}
|
constructor(public _ref: ChangeDetectorRef) {}
|
||||||
|
|
||||||
supports(obj: any): boolean { return true; }
|
|
||||||
|
|
||||||
onDestroy(): void {
|
onDestroy(): void {
|
||||||
if (isPresent(this._subscription)) {
|
if (isPresent(this._subscription)) {
|
||||||
this._dispose();
|
this._dispose();
|
||||||
|
@ -98,13 +98,13 @@ export class AsyncPipe implements Pipe {
|
||||||
this._strategy.createSubscription(obj, value => this._updateLatestValue(obj, value));
|
this._strategy.createSubscription(obj, value => this._updateLatestValue(obj, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
_selectStrategy(obj: Observable | Promise<any>) {
|
_selectStrategy(obj: Observable | Promise<any>): any {
|
||||||
if (isPromise(obj)) {
|
if (isPromise(obj)) {
|
||||||
return _promiseStrategy;
|
return _promiseStrategy;
|
||||||
} else if (ObservableWrapper.isObservable(obj)) {
|
} else if (ObservableWrapper.isObservable(obj)) {
|
||||||
return _observableStrategy;
|
return _observableStrategy;
|
||||||
} else {
|
} else {
|
||||||
throw new BaseException(`Async pipe does not support object '${obj}'`);
|
throw new InvalidPipeArgumentException(AsyncPipe, obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,12 +123,3 @@ export class AsyncPipe implements Pipe {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides a factory for [AsyncPipe].
|
|
||||||
*/
|
|
||||||
@CONST()
|
|
||||||
export class AsyncPipeFactory implements PipeFactory {
|
|
||||||
supports(obj: any): boolean { return true; }
|
|
||||||
create(cdRef: ChangeDetectorRef): Pipe { return new AsyncPipe(cdRef); }
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,12 +5,13 @@ import {
|
||||||
Date,
|
Date,
|
||||||
DateWrapper,
|
DateWrapper,
|
||||||
CONST,
|
CONST,
|
||||||
|
isBlank,
|
||||||
FunctionWrapper
|
FunctionWrapper
|
||||||
} from 'angular2/src/facade/lang';
|
} from 'angular2/src/facade/lang';
|
||||||
import {DateFormatter} from 'angular2/src/facade/intl';
|
import {DateFormatter} from 'angular2/src/facade/intl';
|
||||||
|
import {Injectable} from 'angular2/di';
|
||||||
import {StringMapWrapper, ListWrapper} from 'angular2/src/facade/collection';
|
import {StringMapWrapper, ListWrapper} from 'angular2/src/facade/collection';
|
||||||
import {Pipe, BasePipe, PipeFactory} from './pipe';
|
import {Pipe, BasePipe, InvalidPipeArgumentException} from './pipe';
|
||||||
import {ChangeDetectorRef} from '../change_detector_ref';
|
|
||||||
|
|
||||||
// TODO: move to a global configable location along with other i18n components.
|
// TODO: move to a global configable location along with other i18n components.
|
||||||
var defaultLocale: string = 'en-US';
|
var defaultLocale: string = 'en-US';
|
||||||
|
@ -70,7 +71,8 @@ var defaultLocale: string = 'en-US';
|
||||||
* {{ dateObj | date:'mmss' }} // output is '43:11'
|
* {{ dateObj | date:'mmss' }} // output is '43:11'
|
||||||
*/
|
*/
|
||||||
@CONST()
|
@CONST()
|
||||||
export class DatePipe extends BasePipe implements PipeFactory {
|
@Injectable()
|
||||||
|
export class DatePipe extends BasePipe {
|
||||||
static _ALIASES = {
|
static _ALIASES = {
|
||||||
'medium': 'yMMMdjms',
|
'medium': 'yMMMdjms',
|
||||||
'short': 'yMdjm',
|
'short': 'yMdjm',
|
||||||
|
@ -84,6 +86,12 @@ export class DatePipe extends BasePipe implements PipeFactory {
|
||||||
|
|
||||||
|
|
||||||
transform(value: any, args: List<any>): string {
|
transform(value: any, args: List<any>): string {
|
||||||
|
if (isBlank(value)) return null;
|
||||||
|
|
||||||
|
if (!this.supports(value)) {
|
||||||
|
throw new InvalidPipeArgumentException(DatePipe, value);
|
||||||
|
}
|
||||||
|
|
||||||
var pattern: string = isPresent(args) && args.length > 0 ? args[0] : 'mediumDate';
|
var pattern: string = isPresent(args) && args.length > 0 ? args[0] : 'mediumDate';
|
||||||
if (isNumber(value)) {
|
if (isNumber(value)) {
|
||||||
value = DateWrapper.fromMillis(value);
|
value = DateWrapper.fromMillis(value);
|
||||||
|
@ -95,6 +103,4 @@ export class DatePipe extends BasePipe implements PipeFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
supports(obj: any): boolean { return isDate(obj) || isNumber(obj); }
|
supports(obj: any): boolean { return isDate(obj) || isNumber(obj); }
|
||||||
|
|
||||||
create(cdRef: ChangeDetectorRef): Pipe { return this; }
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import {isBlank, isPresent, Json, CONST} from 'angular2/src/facade/lang';
|
import {isBlank, isPresent, Json, CONST} from 'angular2/src/facade/lang';
|
||||||
import {Pipe, BasePipe, PipeFactory} from './pipe';
|
import {Injectable} from 'angular2/di';
|
||||||
import {ChangeDetectorRef} from '../change_detector_ref';
|
import {Pipe, BasePipe} from './pipe';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements json transforms to any object.
|
* Implements json transforms to any object.
|
||||||
|
@ -26,8 +26,7 @@ import {ChangeDetectorRef} from '../change_detector_ref';
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
@CONST()
|
@CONST()
|
||||||
export class JsonPipe extends BasePipe implements PipeFactory {
|
@Injectable()
|
||||||
|
export class JsonPipe extends BasePipe {
|
||||||
transform(value: any, args: List<any> = null): string { return Json.stringify(value); }
|
transform(value: any, args: List<any> = null): string { return Json.stringify(value); }
|
||||||
|
|
||||||
create(cdRef: ChangeDetectorRef): Pipe { return this; }
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@ import {
|
||||||
} from 'angular2/src/facade/lang';
|
} from 'angular2/src/facade/lang';
|
||||||
import {ListWrapper} from 'angular2/src/facade/collection';
|
import {ListWrapper} from 'angular2/src/facade/collection';
|
||||||
import {Math} from 'angular2/src/facade/math';
|
import {Math} from 'angular2/src/facade/math';
|
||||||
import {WrappedValue, Pipe, PipeFactory} from './pipe';
|
import {Injectable} from 'angular2/di';
|
||||||
import {ChangeDetectorRef} from '../change_detector_ref';
|
import {WrappedValue, Pipe, InvalidPipeArgumentException} from './pipe';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new List or String containing only a prefix/suffix of the
|
* Creates a new List or String containing only a prefix/suffix of the
|
||||||
|
@ -50,15 +50,18 @@ import {ChangeDetectorRef} from '../change_detector_ref';
|
||||||
* {{ 'abcdefghij' | limitTo: -4 }} // output is 'ghij'
|
* {{ 'abcdefghij' | limitTo: -4 }} // output is 'ghij'
|
||||||
* {{ 'abcdefghij' | limitTo: -100 }} // output is 'abcdefghij'
|
* {{ 'abcdefghij' | limitTo: -100 }} // output is 'abcdefghij'
|
||||||
*/
|
*/
|
||||||
|
@Injectable()
|
||||||
export class LimitToPipe implements Pipe {
|
export class LimitToPipe implements Pipe {
|
||||||
static supportsObj(obj: any): boolean { return isString(obj) || isArray(obj); }
|
supports(obj: any): boolean { return isString(obj) || isArray(obj); }
|
||||||
|
|
||||||
supports(obj: any): boolean { return LimitToPipe.supportsObj(obj); }
|
|
||||||
|
|
||||||
transform(value: any, args: List<any> = null): any {
|
transform(value: any, args: List<any> = null): any {
|
||||||
if (isBlank(args) || args.length == 0) {
|
if (isBlank(args) || args.length == 0) {
|
||||||
throw new BaseException('limitTo pipe requires one argument');
|
throw new BaseException('limitTo pipe requires one argument');
|
||||||
}
|
}
|
||||||
|
if (!this.supports(value)) {
|
||||||
|
throw new InvalidPipeArgumentException(LimitToPipe, value);
|
||||||
|
}
|
||||||
|
if (isBlank(value)) return value;
|
||||||
var limit: int = args[0];
|
var limit: int = args[0];
|
||||||
var left = 0, right = Math.min(limit, value.length);
|
var left = 0, right = Math.min(limit, value.length);
|
||||||
if (limit < 0) {
|
if (limit < 0) {
|
||||||
|
@ -73,10 +76,3 @@ export class LimitToPipe implements Pipe {
|
||||||
|
|
||||||
onDestroy(): void {}
|
onDestroy(): void {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@CONST()
|
|
||||||
export class LimitToPipeFactory implements PipeFactory {
|
|
||||||
supports(obj: any): boolean { return LimitToPipe.supportsObj(obj); }
|
|
||||||
|
|
||||||
create(cdRef: ChangeDetectorRef): Pipe { return new LimitToPipe(); }
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import {isString, StringWrapper, CONST} from 'angular2/src/facade/lang';
|
import {isString, StringWrapper, CONST, isBlank} from 'angular2/src/facade/lang';
|
||||||
import {Pipe, BasePipe, PipeFactory} from './pipe';
|
import {Injectable} from 'angular2/di';
|
||||||
import {ChangeDetectorRef} from '../change_detector_ref';
|
import {Pipe, BasePipe, InvalidPipeArgumentException} from './pipe';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements lowercase transforms to text.
|
* Implements lowercase transforms to text.
|
||||||
|
@ -23,12 +23,13 @@ import {ChangeDetectorRef} from '../change_detector_ref';
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
@CONST()
|
@CONST()
|
||||||
export class LowerCasePipe extends BasePipe implements PipeFactory {
|
@Injectable()
|
||||||
supports(str: any): boolean { return isString(str); }
|
export class LowerCasePipe extends BasePipe {
|
||||||
|
|
||||||
transform(value: string, args: List<any> = null): string {
|
transform(value: string, args: List<any> = null): string {
|
||||||
|
if (isBlank(value)) return value;
|
||||||
|
if (!isString(value)) {
|
||||||
|
throw new InvalidPipeArgumentException(LowerCasePipe, value);
|
||||||
|
}
|
||||||
return StringWrapper.toLowerCase(value);
|
return StringWrapper.toLowerCase(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
create(cdRef: ChangeDetectorRef): Pipe { return this; }
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
import {isBlank, CONST} from 'angular2/src/facade/lang';
|
|
||||||
import {Pipe, BasePipe, WrappedValue, PipeFactory} from './pipe';
|
|
||||||
import {ChangeDetectorRef} from '../change_detector_ref';
|
|
||||||
|
|
||||||
@CONST()
|
|
||||||
export class NullPipeFactory implements PipeFactory {
|
|
||||||
supports(obj: any): boolean { return NullPipe.supportsObj(obj); }
|
|
||||||
|
|
||||||
create(cdRef: ChangeDetectorRef): Pipe { return new NullPipe(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
export class NullPipe extends BasePipe {
|
|
||||||
called: boolean = false;
|
|
||||||
|
|
||||||
static supportsObj(obj: any): boolean { return isBlank(obj); }
|
|
||||||
|
|
||||||
supports(obj: any): boolean { return NullPipe.supportsObj(obj); }
|
|
||||||
|
|
||||||
transform(value: any, args: List<any> = null): WrappedValue {
|
|
||||||
if (!this.called) {
|
|
||||||
this.called = true;
|
|
||||||
return WrappedValue.wrap(null);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -10,17 +10,22 @@ import {
|
||||||
FunctionWrapper
|
FunctionWrapper
|
||||||
} from 'angular2/src/facade/lang';
|
} from 'angular2/src/facade/lang';
|
||||||
import {NumberFormatter, NumberFormatStyle} from 'angular2/src/facade/intl';
|
import {NumberFormatter, NumberFormatStyle} from 'angular2/src/facade/intl';
|
||||||
|
import {Injectable} from 'angular2/di';
|
||||||
import {ListWrapper} from 'angular2/src/facade/collection';
|
import {ListWrapper} from 'angular2/src/facade/collection';
|
||||||
import {Pipe, BasePipe, PipeFactory} from './pipe';
|
import {Pipe, BasePipe, InvalidPipeArgumentException} from './pipe';
|
||||||
import {ChangeDetectorRef} from '../change_detector_ref';
|
|
||||||
|
|
||||||
var defaultLocale: string = 'en-US';
|
var defaultLocale: string = 'en-US';
|
||||||
var _re = RegExpWrapper.create('^(\\d+)?\\.((\\d+)(\\-(\\d+))?)?$');
|
var _re = RegExpWrapper.create('^(\\d+)?\\.((\\d+)(\\-(\\d+))?)?$');
|
||||||
|
|
||||||
@CONST()
|
@CONST()
|
||||||
export class NumberPipe extends BasePipe implements PipeFactory {
|
@Injectable()
|
||||||
|
export class NumberPipe extends BasePipe {
|
||||||
static _format(value: number, style: NumberFormatStyle, digits: string, currency: string = null,
|
static _format(value: number, style: NumberFormatStyle, digits: string, currency: string = null,
|
||||||
currencyAsSymbol: boolean = false): string {
|
currencyAsSymbol: boolean = false): string {
|
||||||
|
if (isBlank(value)) return null;
|
||||||
|
if (!isNumber(value)) {
|
||||||
|
throw new InvalidPipeArgumentException(NumberPipe, value);
|
||||||
|
}
|
||||||
var minInt = 1, minFraction = 0, maxFraction = 3;
|
var minInt = 1, minFraction = 0, maxFraction = 3;
|
||||||
if (isPresent(digits)) {
|
if (isPresent(digits)) {
|
||||||
var parts = RegExpWrapper.firstMatch(_re, digits);
|
var parts = RegExpWrapper.firstMatch(_re, digits);
|
||||||
|
@ -45,10 +50,6 @@ export class NumberPipe extends BasePipe implements PipeFactory {
|
||||||
currencyAsSymbol: currencyAsSymbol
|
currencyAsSymbol: currencyAsSymbol
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
supports(obj: any): boolean { return isNumber(obj); }
|
|
||||||
|
|
||||||
create(cdRef: ChangeDetectorRef): Pipe { return this; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import {ABSTRACT, BaseException, CONST} from 'angular2/src/facade/lang';
|
import {ABSTRACT, BaseException, CONST, Type} from 'angular2/src/facade/lang';
|
||||||
import {ChangeDetectorRef} from '../change_detector_ref';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that the result of a {@link Pipe} transformation has changed even though the reference
|
* Indicates that the result of a {@link Pipe} transformation has changed even though the reference
|
||||||
|
@ -50,8 +49,6 @@ export interface Pipe {
|
||||||
/**
|
/**
|
||||||
* Query if a pipe supports a particular object instance.
|
* Query if a pipe supports a particular object instance.
|
||||||
*/
|
*/
|
||||||
supports(obj): boolean;
|
|
||||||
|
|
||||||
onDestroy(): void;
|
onDestroy(): void;
|
||||||
|
|
||||||
transform(value: any, args: List<any>): any;
|
transform(value: any, args: List<any>): any;
|
||||||
|
@ -72,17 +69,14 @@ export interface Pipe {
|
||||||
*/
|
*/
|
||||||
@CONST()
|
@CONST()
|
||||||
export class BasePipe implements Pipe {
|
export class BasePipe implements Pipe {
|
||||||
supports(obj: any): boolean { return true; }
|
|
||||||
onDestroy(): void {}
|
onDestroy(): void {}
|
||||||
transform(value: any, args: List<any>): any { return _abstract(); }
|
transform(value: any, args: List<any>): any { return _abstract(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
export class InvalidPipeArgumentException extends BaseException {
|
||||||
*
|
constructor(type: Type, value: Object) {
|
||||||
*/
|
super(`Invalid argument '${value}' for pipe '${type}'`);
|
||||||
export interface PipeFactory {
|
}
|
||||||
supports(obs): boolean;
|
|
||||||
create(cdRef: ChangeDetectorRef): Pipe;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function _abstract() {
|
function _abstract() {
|
||||||
|
|
|
@ -1,44 +1,42 @@
|
||||||
import {ListWrapper, isListLikeIterable, StringMapWrapper} from 'angular2/src/facade/collection';
|
import {ListWrapper, isListLikeIterable, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||||
import {isBlank, isPresent, BaseException, CONST} from 'angular2/src/facade/lang';
|
import {isBlank, isPresent, BaseException, CONST, Type} from 'angular2/src/facade/lang';
|
||||||
import {Pipe, PipeFactory} from './pipe';
|
import {Pipe} from './pipe';
|
||||||
import {Injectable, OptionalMetadata, SkipSelfMetadata} from 'angular2/di';
|
import {Injectable, OptionalMetadata, SkipSelfMetadata, Binding, Injector, bind} from 'angular2/di';
|
||||||
import {ChangeDetectorRef} from '../change_detector_ref';
|
import {ChangeDetectorRef} from '../change_detector_ref';
|
||||||
import {Binding} from 'angular2/di';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@CONST()
|
@CONST()
|
||||||
export class Pipes {
|
export class Pipes {
|
||||||
/**
|
/**
|
||||||
* Map of {@link Pipe} names to {@link PipeFactory} lists used to configure the
|
* Map of {@link Pipe} names to {@link Pipe} implementations.
|
||||||
* {@link Pipes} registry.
|
|
||||||
*
|
*
|
||||||
* #Example
|
* #Example
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
* var pipesConfig = {
|
* var pipesConfig = {
|
||||||
* 'json': [jsonPipeFactory]
|
* 'json': JsonPipe
|
||||||
* }
|
* }
|
||||||
* @Component({
|
* @Component({
|
||||||
* viewBindings: [
|
* viewBindings: [
|
||||||
* bind(Pipes).toValue(new Pipes(pipesConfig))
|
* bind(Pipes).toFactory(inj => new Pipes(pipesConfig, in), [Injector])
|
||||||
* ]
|
* ]
|
||||||
* })
|
* })
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
config: StringMap<string, PipeFactory[]>;
|
config: StringMap<string, Type | Binding>;
|
||||||
|
|
||||||
|
constructor(config: StringMap<string, Type | Binding>, public injector: Injector) {
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(config: StringMap<string, PipeFactory[]>) { this.config = config; }
|
get(type: string, cdRef: ChangeDetectorRef): Pipe {
|
||||||
|
var typeOrBinding = this.config[type];
|
||||||
get(type: string, obj: any, cdRef?: ChangeDetectorRef, existingPipe?: Pipe): Pipe {
|
if (isBlank(typeOrBinding)) {
|
||||||
if (isPresent(existingPipe) && existingPipe.supports(obj)) return existingPipe;
|
throw new BaseException(`Cannot find pipe '${type}'.`);
|
||||||
|
}
|
||||||
if (isPresent(existingPipe)) existingPipe.onDestroy();
|
// this is a temporary workaround and will be removed
|
||||||
|
return this.injector.resolveAndCreateChild([bind(ChangeDetectorRef).toValue(cdRef)])
|
||||||
var factories = this._getListOfFactories(type, obj);
|
.resolveAndInstantiate(typeOrBinding);
|
||||||
var factory = this._getMatchingFactory(factories, type, obj);
|
|
||||||
|
|
||||||
return factory.create(cdRef);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -46,16 +44,7 @@ export class Pipes {
|
||||||
* inherited {@link Pipes} instance with the provided config and return a new
|
* inherited {@link Pipes} instance with the provided config and return a new
|
||||||
* {@link Pipes} instance.
|
* {@link Pipes} instance.
|
||||||
*
|
*
|
||||||
* If the provided config contains a key that is not yet present in the
|
* The provided config is merged with the {@link Pipes} instance.
|
||||||
* inherited {@link Pipes}' config, a new {@link PipeFactory} list will be created
|
|
||||||
* for that key. Otherwise, the provided config will be merged with the inherited
|
|
||||||
* {@link Pipes} instance by prepending pipes to their respective keys, without mutating
|
|
||||||
* the inherited {@link Pipes}.
|
|
||||||
*
|
|
||||||
* The following example shows how to extend an existing list of `async` factories
|
|
||||||
* with a new {@link PipeFactory}, which will only be applied to the injector
|
|
||||||
* for this component and its children. This step is all that's required to make a new
|
|
||||||
* pipe available to this component's template.
|
|
||||||
*
|
*
|
||||||
* # Example
|
* # Example
|
||||||
*
|
*
|
||||||
|
@ -63,55 +52,33 @@ export class Pipes {
|
||||||
* @Component({
|
* @Component({
|
||||||
* viewBindings: [
|
* viewBindings: [
|
||||||
* Pipes.extend({
|
* Pipes.extend({
|
||||||
* async: [newAsyncPipe]
|
* 'bithdayFormat': BirthdayFormat
|
||||||
* })
|
* })
|
||||||
* ]
|
* ]
|
||||||
* })
|
* })
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
static extend(config: StringMap<string, PipeFactory[]>): Binding {
|
static extend(config: StringMap<string, Type | Binding>): Binding {
|
||||||
return new Binding(Pipes, {
|
return new Binding(Pipes, {
|
||||||
toFactory: (pipes: Pipes) => {
|
toFactory: (pipes: Pipes, injector: Injector) => {
|
||||||
if (isBlank(pipes)) {
|
if (isBlank(pipes)) {
|
||||||
// Typically would occur when calling Pipe.extend inside of dependencies passed to
|
// Typically would occur when calling Pipe.extend inside of dependencies passed to
|
||||||
// bootstrap(), which would override default pipes instead of extending them.
|
// bootstrap(), which would override default pipes instead of extending them.
|
||||||
throw new BaseException('Cannot extend Pipes without a parent injector');
|
throw new BaseException('Cannot extend Pipes without a parent injector');
|
||||||
}
|
}
|
||||||
return Pipes.create(config, pipes);
|
return Pipes.create(config, injector, pipes);
|
||||||
},
|
},
|
||||||
// Dependency technically isn't optional, but we can provide a better error message this way.
|
// Dependency technically isn't optional, but we can provide a better error message this way.
|
||||||
deps: [[Pipes, new SkipSelfMetadata(), new OptionalMetadata()]]
|
deps: [[Pipes, new SkipSelfMetadata(), new OptionalMetadata()], Injector]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static create(config: StringMap<string, PipeFactory[]>, pipes: Pipes = null): Pipes {
|
static create(config: StringMap<string, Type | Binding>, injector: Injector,
|
||||||
|
pipes: Pipes = null): Pipes {
|
||||||
if (isPresent(pipes)) {
|
if (isPresent(pipes)) {
|
||||||
StringMapWrapper.forEach(pipes.config, (v: PipeFactory[], k: string) => {
|
return new Pipes(StringMapWrapper.merge(pipes.config, config), injector);
|
||||||
if (StringMapWrapper.contains(config, k)) {
|
} else {
|
||||||
var configFactories: PipeFactory[] = config[k];
|
return new Pipes(config, injector);
|
||||||
config[k] = configFactories.concat(v);
|
|
||||||
} else {
|
|
||||||
config[k] = ListWrapper.clone(v);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return new Pipes(config);
|
|
||||||
}
|
|
||||||
|
|
||||||
private _getListOfFactories(type: string, obj: any): PipeFactory[] {
|
|
||||||
var listOfFactories = this.config[type];
|
|
||||||
if (isBlank(listOfFactories)) {
|
|
||||||
throw new BaseException(`Cannot find '${type}' pipe supporting object '${obj}'`);
|
|
||||||
}
|
|
||||||
return listOfFactories;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _getMatchingFactory(listOfFactories: PipeFactory[], type: string, obj: any): PipeFactory {
|
|
||||||
var matchingFactory =
|
|
||||||
ListWrapper.find(listOfFactories, pipeFactory => pipeFactory.supports(obj));
|
|
||||||
if (isBlank(matchingFactory)) {
|
|
||||||
throw new BaseException(`Cannot find '${type}' pipe supporting object '${obj}'`);
|
|
||||||
}
|
|
||||||
return matchingFactory;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import {isString, StringWrapper, CONST} from 'angular2/src/facade/lang';
|
import {isString, StringWrapper, CONST, isBlank} from 'angular2/src/facade/lang';
|
||||||
import {Pipe, BasePipe, PipeFactory} from './pipe';
|
import {Injectable} from 'angular2/di';
|
||||||
import {ChangeDetectorRef} from '../change_detector_ref';
|
import {Pipe, BasePipe, InvalidPipeArgumentException} from './pipe';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements uppercase transforms to text.
|
* Implements uppercase transforms to text.
|
||||||
|
@ -23,12 +23,13 @@ import {ChangeDetectorRef} from '../change_detector_ref';
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
@CONST()
|
@CONST()
|
||||||
export class UpperCasePipe extends BasePipe implements PipeFactory {
|
@Injectable()
|
||||||
supports(str: any): boolean { return isString(str); }
|
export class UpperCasePipe extends BasePipe {
|
||||||
|
|
||||||
transform(value: string, args: List<any> = null): string {
|
transform(value: string, args: List<any> = null): string {
|
||||||
|
if (isBlank(value)) return value;
|
||||||
|
if (!isString(value)) {
|
||||||
|
throw new InvalidPipeArgumentException(UpperCasePipe, value);
|
||||||
|
}
|
||||||
return StringWrapper.toUpperCase(value);
|
return StringWrapper.toUpperCase(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
create(cdRef: ChangeDetectorRef): Pipe { return this; }
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,7 +137,7 @@ function _injectorBindings(appComponentType): List<Type | Binding | List<any>> {
|
||||||
Compiler,
|
Compiler,
|
||||||
CompilerCache,
|
CompilerCache,
|
||||||
ViewResolver,
|
ViewResolver,
|
||||||
bind(Pipes).toValue(defaultPipes),
|
defaultPipes,
|
||||||
bind(IterableDiffers).toValue(defaultIterableDiffers),
|
bind(IterableDiffers).toValue(defaultIterableDiffers),
|
||||||
bind(KeyValueDiffers).toValue(defaultKeyValueDiffers),
|
bind(KeyValueDiffers).toValue(defaultKeyValueDiffers),
|
||||||
bind(ChangeDetection).toClass(bestChangeDetection),
|
bind(ChangeDetection).toClass(bestChangeDetection),
|
||||||
|
|
|
@ -558,7 +558,7 @@ export class Injector {
|
||||||
* @param `binding`: either a type or a binding.
|
* @param `binding`: either a type or a binding.
|
||||||
* @returns an object created using binding.
|
* @returns an object created using binding.
|
||||||
*/
|
*/
|
||||||
resolveAndInstantiate(binding: Type | Binding) {
|
resolveAndInstantiate(binding: Type | Binding): any {
|
||||||
return this.instantiateResolved(Injector.resolve([binding])[0]);
|
return this.instantiateResolved(Injector.resolve([binding])[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,11 +19,6 @@ class SpyPipe extends SpyObject implements Pipe {
|
||||||
noSuchMethod(m) => super.noSuchMethod(m);
|
noSuchMethod(m) => super.noSuchMethod(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
@proxy()
|
|
||||||
class SpyPipeFactory extends SpyObject implements PipeFactory {
|
|
||||||
noSuchMethod(m) => super.noSuchMethod(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
@proxy()
|
@proxy()
|
||||||
class SpyDependencyProvider extends SpyObject implements DependencyProvider {
|
class SpyDependencyProvider extends SpyObject implements DependencyProvider {
|
||||||
noSuchMethod(m) => super.noSuchMethod(m);
|
noSuchMethod(m) => super.noSuchMethod(m);
|
||||||
|
@ -39,3 +34,8 @@ class SpyIterableDifferFactory extends SpyObject
|
||||||
implements IterableDifferFactory {
|
implements IterableDifferFactory {
|
||||||
noSuchMethod(m) => super.noSuchMethod(m);
|
noSuchMethod(m) => super.noSuchMethod(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@proxy
|
||||||
|
class SpyInjector extends SpyObject implements Injector {
|
||||||
|
noSuchMethod(m) => super.noSuchMethod(m);
|
||||||
|
}
|
||||||
|
|
|
@ -22,12 +22,12 @@ export class SpyPipe extends SpyObject {
|
||||||
constructor() { super(BasePipe); }
|
constructor() { super(BasePipe); }
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SpyPipeFactory extends SpyObject {}
|
|
||||||
|
|
||||||
export class SpyDependencyProvider extends SpyObject {}
|
export class SpyDependencyProvider extends SpyObject {}
|
||||||
|
|
||||||
export class SpyIterableDifferFactory extends SpyObject {}
|
export class SpyIterableDifferFactory extends SpyObject {}
|
||||||
|
|
||||||
|
export class SpyInjector extends SpyObject {}
|
||||||
|
|
||||||
export class SpyChangeDetectorRef extends SpyObject {
|
export class SpyChangeDetectorRef extends SpyObject {
|
||||||
constructor() { super(ChangeDetectorRef); }
|
constructor() { super(ChangeDetectorRef); }
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,7 +122,7 @@ function _getAppBindings() {
|
||||||
Compiler,
|
Compiler,
|
||||||
CompilerCache,
|
CompilerCache,
|
||||||
bind(ViewResolver).toClass(MockViewResolver),
|
bind(ViewResolver).toClass(MockViewResolver),
|
||||||
bind(Pipes).toValue(defaultPipes),
|
defaultPipes,
|
||||||
bind(IterableDiffers).toValue(defaultIterableDiffers),
|
bind(IterableDiffers).toValue(defaultIterableDiffers),
|
||||||
bind(KeyValueDiffers).toValue(defaultKeyValueDiffers),
|
bind(KeyValueDiffers).toValue(defaultKeyValueDiffers),
|
||||||
bind(ChangeDetection).toClass(DynamicChangeDetection),
|
bind(ChangeDetection).toClass(DynamicChangeDetection),
|
||||||
|
|
|
@ -274,10 +274,7 @@ class _CodegenState {
|
||||||
|
|
||||||
var read = '''
|
var read = '''
|
||||||
if ($_IDENTICAL_CHECK_FN($pipe, $_UTIL.uninitialized)) {
|
if ($_IDENTICAL_CHECK_FN($pipe, $_UTIL.uninitialized)) {
|
||||||
$pipe = ${_names.getPipesAccessorName()}.get('$pipeType', $context, $cdRef);
|
$pipe = ${_names.getPipesAccessorName()}.get('$pipeType', $cdRef);
|
||||||
} else if (!$pipe.supports($context)) {
|
|
||||||
$pipe.onDestroy();
|
|
||||||
$pipe = ${_names.getPipesAccessorName()}.get('$pipeType', $context, $cdRef);
|
|
||||||
}
|
}
|
||||||
$newValue = $pipe.transform($context, [$argString]);
|
$newValue = $pipe.transform($context, [$argString]);
|
||||||
''';
|
''';
|
||||||
|
|
|
@ -118,7 +118,7 @@ function _injectorBindings(appComponentType, bus: WorkerMessageBus,
|
||||||
Compiler,
|
Compiler,
|
||||||
CompilerCache,
|
CompilerCache,
|
||||||
ViewResolver,
|
ViewResolver,
|
||||||
bind(Pipes).toValue(defaultPipes),
|
defaultPipes,
|
||||||
bind(ChangeDetection).toClass(bestChangeDetection),
|
bind(ChangeDetection).toClass(bestChangeDetection),
|
||||||
DirectiveResolver,
|
DirectiveResolver,
|
||||||
Parser,
|
Parser,
|
||||||
|
|
|
@ -768,7 +768,7 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should destroy all active pipes during dehyration', () => {
|
it('should destroy all active pipes during dehyration', () => {
|
||||||
var pipe = new OncePipe();
|
var pipe = new PipeWithOnDestroy();
|
||||||
var registry = new FakePipes('pipe', () => pipe);
|
var registry = new FakePipes('pipe', () => pipe);
|
||||||
var cd = _createChangeDetector('name | pipe', new Person('bob'), registry).changeDetector;
|
var cd = _createChangeDetector('name | pipe', new Person('bob'), registry).changeDetector;
|
||||||
|
|
||||||
|
@ -810,36 +810,6 @@ export function main() {
|
||||||
expect(val.dispatcher.log).toEqual(['propName=Megatron state:1']);
|
expect(val.dispatcher.log).toEqual(['propName=Megatron state:1']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should lookup pipes in the registry when the context is not supported', () => {
|
|
||||||
var registry = new FakePipes('pipe', () => new OncePipe());
|
|
||||||
var ctx = new Person('Megatron');
|
|
||||||
|
|
||||||
var cd = _createChangeDetector('name | pipe', ctx, registry).changeDetector;
|
|
||||||
|
|
||||||
cd.detectChanges();
|
|
||||||
|
|
||||||
expect(registry.numberOfLookups).toEqual(1);
|
|
||||||
|
|
||||||
ctx.name = 'Optimus Prime';
|
|
||||||
cd.detectChanges();
|
|
||||||
|
|
||||||
expect(registry.numberOfLookups).toEqual(2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should invoke onDestroy on a pipe before switching to another one', () => {
|
|
||||||
var pipe = new OncePipe();
|
|
||||||
var registry = new FakePipes('pipe', () => pipe);
|
|
||||||
var ctx = new Person('Megatron');
|
|
||||||
|
|
||||||
var cd = _createChangeDetector('name | pipe', ctx, registry).changeDetector;
|
|
||||||
|
|
||||||
cd.detectChanges();
|
|
||||||
ctx.name = 'Optimus Prime';
|
|
||||||
cd.detectChanges();
|
|
||||||
|
|
||||||
expect(pipe.destroyCalled).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should inject the ChangeDetectorRef ' +
|
it('should inject the ChangeDetectorRef ' +
|
||||||
'of the encompassing component into a pipe',
|
'of the encompassing component into a pipe',
|
||||||
() => {
|
() => {
|
||||||
|
@ -886,41 +856,24 @@ export function main() {
|
||||||
|
|
||||||
class CountingPipe implements Pipe {
|
class CountingPipe implements Pipe {
|
||||||
state: number = 0;
|
state: number = 0;
|
||||||
|
|
||||||
onDestroy() {}
|
onDestroy() {}
|
||||||
|
|
||||||
supports(newValue) { return true; }
|
|
||||||
|
|
||||||
transform(value, args = null) { return `${value} state:${this.state ++}`; }
|
transform(value, args = null) { return `${value} state:${this.state ++}`; }
|
||||||
}
|
}
|
||||||
|
|
||||||
class OncePipe implements Pipe {
|
class PipeWithOnDestroy implements Pipe {
|
||||||
called: boolean = false;
|
|
||||||
destroyCalled: boolean = false;
|
destroyCalled: boolean = false;
|
||||||
|
|
||||||
supports(newValue) { return !this.called; }
|
|
||||||
|
|
||||||
onDestroy() { this.destroyCalled = true; }
|
onDestroy() { this.destroyCalled = true; }
|
||||||
|
|
||||||
transform(value, args = null) {
|
transform(value, args = null) { return null; }
|
||||||
this.called = true;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class IdentityPipe implements Pipe {
|
class IdentityPipe implements Pipe {
|
||||||
supports(obj): boolean { return true; }
|
|
||||||
|
|
||||||
onDestroy() {}
|
onDestroy() {}
|
||||||
|
|
||||||
transform(value, args = null) { return value; }
|
transform(value, args = null) { return value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
class WrappedPipe implements Pipe {
|
class WrappedPipe implements Pipe {
|
||||||
supports(obj): boolean { return true; }
|
|
||||||
|
|
||||||
onDestroy() {}
|
onDestroy() {}
|
||||||
|
|
||||||
transform(value, args = null) { return WrappedValue.wrap(value); }
|
transform(value, args = null) { return WrappedValue.wrap(value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -931,24 +884,16 @@ class MultiArgPipe implements Pipe {
|
||||||
var arg3 = args.length > 2 ? args[2] : 'default';
|
var arg3 = args.length > 2 ? args[2] : 'default';
|
||||||
return `${value} ${arg1} ${arg2} ${arg3}`;
|
return `${value} ${arg1} ${arg2} ${arg3}`;
|
||||||
}
|
}
|
||||||
supports(obj): boolean { return true; }
|
|
||||||
onDestroy(): void {}
|
onDestroy(): void {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FakePipes extends Pipes {
|
class FakePipes extends Pipes {
|
||||||
numberOfLookups: number;
|
numberOfLookups = 0;
|
||||||
pipeType: string;
|
|
||||||
factory: Function;
|
|
||||||
cdRef: any;
|
cdRef: any;
|
||||||
|
|
||||||
constructor(pipeType, factory) {
|
constructor(public pipeType: string, public factory: Function) { super(null, null); }
|
||||||
super({});
|
|
||||||
this.pipeType = pipeType;
|
|
||||||
this.factory = factory;
|
|
||||||
this.numberOfLookups = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
get(type: string, obj, cdRef?, existingPipe?) {
|
get(type: string, cdRef?) {
|
||||||
if (type != this.pipeType) return null;
|
if (type != this.pipeType) return null;
|
||||||
this.numberOfLookups++;
|
this.numberOfLookups++;
|
||||||
this.cdRef = cdRef;
|
this.cdRef = cdRef;
|
||||||
|
|
|
@ -20,10 +20,8 @@ import {JsonPipe} from 'angular2/src/change_detection/pipes/json_pipe';
|
||||||
export function main() {
|
export function main() {
|
||||||
describe("JsonPipe", () => {
|
describe("JsonPipe", () => {
|
||||||
var regNewLine = '\n';
|
var regNewLine = '\n';
|
||||||
var canHasUndefined; // because Dart doesn't like undefined;
|
|
||||||
var inceptionObj;
|
var inceptionObj;
|
||||||
var inceptionObjString;
|
var inceptionObjString;
|
||||||
var catString;
|
|
||||||
var pipe;
|
var pipe;
|
||||||
var collection: number[];
|
var collection: number[];
|
||||||
|
|
||||||
|
@ -35,27 +33,10 @@ export function main() {
|
||||||
" \"dream\": \"Limbo\"\n" + " }\n" + " }\n" + "}";
|
" \"dream\": \"Limbo\"\n" + " }\n" + " }\n" + "}";
|
||||||
|
|
||||||
|
|
||||||
catString = 'Inception Cat';
|
|
||||||
pipe = new JsonPipe();
|
pipe = new JsonPipe();
|
||||||
collection = [];
|
collection = [];
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("supports", () => {
|
|
||||||
it("should support objects", () => { expect(pipe.supports(inceptionObj)).toBe(true); });
|
|
||||||
|
|
||||||
it("should support strings", () => { expect(pipe.supports(catString)).toBe(true); });
|
|
||||||
|
|
||||||
it("should support null", () => { expect(pipe.supports(null)).toBe(true); });
|
|
||||||
|
|
||||||
it("should support NaN", () => { expect(pipe.supports(NumberWrapper.NaN)).toBe(true); });
|
|
||||||
|
|
||||||
if (!IS_DARTIUM) {
|
|
||||||
it("should support undefined",
|
|
||||||
() => { expect(pipe.supports(canHasUndefined)).toBe(true); });
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("transform", () => {
|
describe("transform", () => {
|
||||||
it("should return JSON-formatted string",
|
it("should return JSON-formatted string",
|
||||||
() => { expect(pipe.transform(inceptionObj)).toEqual(inceptionObjString); });
|
() => { expect(pipe.transform(inceptionObj)).toEqual(inceptionObjString); });
|
||||||
|
|
|
@ -4,29 +4,17 @@ import {LowerCasePipe} from 'angular2/src/change_detection/pipes/lowercase_pipe'
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
describe("LowerCasePipe", () => {
|
describe("LowerCasePipe", () => {
|
||||||
var str;
|
|
||||||
var upper;
|
var upper;
|
||||||
var lower;
|
var lower;
|
||||||
var pipe;
|
var pipe;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
str = 'something';
|
|
||||||
lower = 'something';
|
lower = 'something';
|
||||||
upper = 'SOMETHING';
|
upper = 'SOMETHING';
|
||||||
pipe = new LowerCasePipe();
|
pipe = new LowerCasePipe();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("supports", () => {
|
|
||||||
it("should support strings", () => { expect(pipe.supports(str)).toBe(true); });
|
|
||||||
|
|
||||||
it("should not support other objects", () => {
|
|
||||||
expect(pipe.supports(new Object())).toBe(false);
|
|
||||||
expect(pipe.supports(null)).toBe(false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("transform", () => {
|
describe("transform", () => {
|
||||||
|
|
||||||
it("should return lowercase", () => {
|
it("should return lowercase", () => {
|
||||||
var val = pipe.transform(upper);
|
var val = pipe.transform(upper);
|
||||||
expect(val).toEqual(lower);
|
expect(val).toEqual(lower);
|
||||||
|
@ -39,6 +27,8 @@ export function main() {
|
||||||
expect(val2).toEqual('wat');
|
expect(val2).toEqual('wat');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should not support other objects",
|
||||||
|
() => { expect(() => pipe.transform(new Object())).toThrowError(); });
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -12,18 +12,8 @@ export function main() {
|
||||||
|
|
||||||
beforeEach(() => { pipe = new DecimalPipe(); });
|
beforeEach(() => { pipe = new DecimalPipe(); });
|
||||||
|
|
||||||
describe("supports", () => {
|
|
||||||
it("should support numbers", () => { expect(pipe.supports(123.0)).toBe(true); });
|
|
||||||
|
|
||||||
it("should not support other objects", () => {
|
|
||||||
expect(pipe.supports(new Object())).toBe(false);
|
|
||||||
expect(pipe.supports('str')).toBe(false);
|
|
||||||
expect(pipe.supports(null)).toBe(false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("transform", () => {
|
describe("transform", () => {
|
||||||
it('should return correct value', () => {
|
it('should return correct value for numbers', () => {
|
||||||
expect(pipe.transform(12345, [])).toEqual('12,345');
|
expect(pipe.transform(12345, [])).toEqual('12,345');
|
||||||
expect(pipe.transform(123, ['.2'])).toEqual('123.00');
|
expect(pipe.transform(123, ['.2'])).toEqual('123.00');
|
||||||
expect(pipe.transform(1, ['3.'])).toEqual('001');
|
expect(pipe.transform(1, ['3.'])).toEqual('001');
|
||||||
|
@ -31,6 +21,9 @@ export function main() {
|
||||||
expect(pipe.transform(1.123456, ['3.4-5'])).toEqual('001.12346');
|
expect(pipe.transform(1.123456, ['3.4-5'])).toEqual('001.12346');
|
||||||
expect(pipe.transform(1.1234, [])).toEqual('1.123');
|
expect(pipe.transform(1.1234, [])).toEqual('1.123');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should not support other objects",
|
||||||
|
() => { expect(() => pipe.transform(new Object(), [])).toThrowError(); });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -39,21 +32,14 @@ export function main() {
|
||||||
|
|
||||||
beforeEach(() => { pipe = new PercentPipe(); });
|
beforeEach(() => { pipe = new PercentPipe(); });
|
||||||
|
|
||||||
describe("supports", () => {
|
|
||||||
it("should support numbers", () => { expect(pipe.supports(123.0)).toBe(true); });
|
|
||||||
|
|
||||||
it("should not support other objects", () => {
|
|
||||||
expect(pipe.supports(new Object())).toBe(false);
|
|
||||||
expect(pipe.supports('str')).toBe(false);
|
|
||||||
expect(pipe.supports(null)).toBe(false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("transform", () => {
|
describe("transform", () => {
|
||||||
it('should return correct value', () => {
|
it('should return correct value for numbers', () => {
|
||||||
expect(pipe.transform(1.23, [])).toEqual('123%');
|
expect(pipe.transform(1.23, [])).toEqual('123%');
|
||||||
expect(pipe.transform(1.2, ['.2'])).toEqual('120.00%');
|
expect(pipe.transform(1.2, ['.2'])).toEqual('120.00%');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should not support other objects",
|
||||||
|
() => { expect(() => pipe.transform(new Object(), [])).toThrowError(); });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -62,21 +48,14 @@ export function main() {
|
||||||
|
|
||||||
beforeEach(() => { pipe = new CurrencyPipe(); });
|
beforeEach(() => { pipe = new CurrencyPipe(); });
|
||||||
|
|
||||||
describe("supports", () => {
|
|
||||||
it("should support numbers", () => { expect(pipe.supports(123.0)).toBe(true); });
|
|
||||||
|
|
||||||
it("should not support other objects", () => {
|
|
||||||
expect(pipe.supports(new Object())).toBe(false);
|
|
||||||
expect(pipe.supports('str')).toBe(false);
|
|
||||||
expect(pipe.supports(null)).toBe(false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("transform", () => {
|
describe("transform", () => {
|
||||||
it('should return correct value', () => {
|
it('should return correct value for numbers', () => {
|
||||||
expect(pipe.transform(123, [])).toEqual('USD123');
|
expect(pipe.transform(123, [])).toEqual('USD123');
|
||||||
expect(pipe.transform(12, ['EUR', false, '.2'])).toEqual('EUR12.00');
|
expect(pipe.transform(12, ['EUR', false, '.2'])).toEqual('EUR12.00');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should not support other objects",
|
||||||
|
() => { expect(() => pipe.transform(new Object(), [])).toThrowError(); });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,158 +1,88 @@
|
||||||
import {
|
import {
|
||||||
ddescribe,
|
ddescribe,
|
||||||
|
xdescribe,
|
||||||
describe,
|
describe,
|
||||||
it,
|
it,
|
||||||
iit,
|
iit,
|
||||||
xit,
|
xit,
|
||||||
expect,
|
expect,
|
||||||
beforeEach,
|
beforeEach,
|
||||||
afterEach,
|
afterEach
|
||||||
SpyPipe,
|
|
||||||
SpyPipeFactory
|
|
||||||
} from 'angular2/test_lib';
|
} from 'angular2/test_lib';
|
||||||
|
|
||||||
import {Injector, bind} from 'angular2/di';
|
import {Injector, bind} from 'angular2/di';
|
||||||
import {Pipes} from 'angular2/src/change_detection/pipes/pipes';
|
import {Pipes} from 'angular2/src/change_detection/pipes/pipes';
|
||||||
import {PipeFactory} from 'angular2/src/change_detection/pipes/pipe';
|
import {Pipe} from 'angular2/src/change_detection/pipes/pipe';
|
||||||
|
|
||||||
|
class APipe implements Pipe {
|
||||||
|
transform(a, b) {}
|
||||||
|
onDestroy() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AnotherPipe implements Pipe {
|
||||||
|
transform(a, b) {}
|
||||||
|
onDestroy() {}
|
||||||
|
}
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
describe("pipe registry", () => {
|
describe("pipe registry", () => {
|
||||||
var firstPipe;
|
var injector;
|
||||||
var secondPipe;
|
|
||||||
|
|
||||||
var firstPipeFactory;
|
beforeEach(() => { injector = Injector.resolveAndCreate([]); });
|
||||||
var secondPipeFactory;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
it("should instantiate a pipe", () => {
|
||||||
firstPipe = <any>new SpyPipe();
|
var r = new Pipes({"type": APipe}, injector);
|
||||||
secondPipe = <any>new SpyPipe();
|
expect(r.get("type", null)).toBeAnInstanceOf(APipe);
|
||||||
|
|
||||||
firstPipeFactory = <any>new SpyPipeFactory();
|
|
||||||
secondPipeFactory = <any>new SpyPipeFactory();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return an existing pipe if it can support the passed in object", () => {
|
it("should instantiate a new pipe every time", () => {
|
||||||
var r = new Pipes({"type": []});
|
var r = new Pipes({"type": APipe}, injector);
|
||||||
|
var p1 = r.get("type", null);
|
||||||
firstPipe.spy("supports").andReturn(true);
|
var p2 = r.get("type", null);
|
||||||
|
expect(p1).not.toBe(p2);
|
||||||
expect(r.get("type", "some object", null, firstPipe)).toEqual(firstPipe);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should call onDestroy on the provided pipe if it cannot support the provided object",
|
|
||||||
() => {
|
|
||||||
firstPipe.spy("supports").andReturn(false);
|
|
||||||
firstPipeFactory.spy("supports").andReturn(true);
|
|
||||||
firstPipeFactory.spy("create").andReturn(secondPipe);
|
|
||||||
|
|
||||||
var r = new Pipes({"type": [firstPipeFactory]});
|
|
||||||
|
|
||||||
expect(r.get("type", "some object", null, firstPipe)).toEqual(secondPipe);
|
|
||||||
expect(firstPipe.spy("onDestroy")).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return the first pipe supporting the data type", () => {
|
|
||||||
firstPipeFactory.spy("supports").andReturn(false);
|
|
||||||
firstPipeFactory.spy("create").andReturn(firstPipe);
|
|
||||||
|
|
||||||
secondPipeFactory.spy("supports").andReturn(true);
|
|
||||||
secondPipeFactory.spy("create").andReturn(secondPipe);
|
|
||||||
|
|
||||||
var r = new Pipes({"type": [firstPipeFactory, secondPipeFactory]});
|
|
||||||
|
|
||||||
expect(r.get("type", "some object")).toBe(secondPipe);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should throw when no matching type", () => {
|
it("should throw when no matching type", () => {
|
||||||
var r = new Pipes({});
|
var r = new Pipes({}, null);
|
||||||
expect(() => r.get("unknown", "some object"))
|
expect(() => r.get("unknown", null)).toThrowError(`Cannot find pipe 'unknown'.`);
|
||||||
.toThrowError(`Cannot find 'unknown' pipe supporting object 'some object'`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should throw when no matching pipe", () => {
|
|
||||||
var r = new Pipes({"type": []});
|
|
||||||
|
|
||||||
expect(() => r.get("type", "some object"))
|
|
||||||
.toThrowError(`Cannot find 'type' pipe supporting object 'some object'`);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('.create()', () => {
|
describe('.create()', () => {
|
||||||
it("should create a new Pipes object", () => {
|
it("should create a new Pipes object", () => {
|
||||||
firstPipeFactory.spy("supports").andReturn(true);
|
var pipes = Pipes.create({'pipe': APipe}, null);
|
||||||
firstPipeFactory.spy("create").andReturn(firstPipe);
|
expect(pipes.config).toEqual({'pipe': APipe});
|
||||||
|
|
||||||
var pipes = Pipes.create({'async': [firstPipeFactory]});
|
|
||||||
expect(pipes.get("async", "first")).toBe(firstPipe);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should prepend passed it config in existing registry", () => {
|
it("should merge pipes config", () => {
|
||||||
firstPipeFactory.spy("supports").andReturn(true);
|
var pipes1 = Pipes.create({'pipe': APipe, 'pipe1': APipe}, null);
|
||||||
secondPipeFactory.spy("supports").andReturn(true);
|
var pipes2 = Pipes.create({'pipe': AnotherPipe, 'pipe2': AnotherPipe}, null, pipes1);
|
||||||
secondPipeFactory.spy("create").andReturn(secondPipe);
|
|
||||||
|
|
||||||
var pipes1 = Pipes.create({'async': [firstPipeFactory]});
|
expect(pipes2.config).toEqual({'pipe': AnotherPipe, 'pipe1': APipe, 'pipe2': AnotherPipe});
|
||||||
var pipes2 = Pipes.create({'async': [secondPipeFactory]}, pipes1);
|
|
||||||
|
|
||||||
expect(pipes2.get("async", "first")).toBe(secondPipe);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should use inherited pipes when no overrides support the provided object", () => {
|
it("should not change parent's config", () => {
|
||||||
firstPipeFactory.spy("supports").andReturn(true);
|
var pipes1 = Pipes.create({'pipe': APipe, 'pipe1': APipe}, null);
|
||||||
firstPipeFactory.spy("create").andReturn(firstPipe);
|
Pipes.create({'pipe': AnotherPipe, 'pipe2': AnotherPipe}, null, pipes1);
|
||||||
secondPipeFactory.spy("supports").andReturn(false);
|
|
||||||
|
|
||||||
var pipes1 = Pipes.create({'async': [firstPipeFactory], 'date': [firstPipeFactory]});
|
expect(pipes1.config).toEqual({'pipe': APipe, 'pipe1': APipe});
|
||||||
var pipes2 = Pipes.create({'async': [secondPipeFactory]}, pipes1);
|
|
||||||
|
|
||||||
expect(pipes2.get("async", "first")).toBe(firstPipe);
|
|
||||||
expect(pipes2.get("date", "first")).toBe(firstPipe);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe(".extend()", () => {
|
describe(".extend()", () => {
|
||||||
it('should create a factory that prepend new pipes to old', () => {
|
it('should create a factory that prepend new pipes to old', () => {
|
||||||
firstPipeFactory.spy("supports").andReturn(true);
|
var pipes1 = Pipes.create({'pipe': APipe, 'pipe1': APipe}, null);
|
||||||
secondPipeFactory.spy("supports").andReturn(true);
|
var binding = Pipes.extend({'pipe': AnotherPipe, 'pipe2': AnotherPipe});
|
||||||
secondPipeFactory.spy("create").andReturn(secondPipe);
|
var pipes: Pipes = binding.toFactory(pipes1, injector);
|
||||||
|
|
||||||
var originalPipes = new Pipes({'async': [firstPipeFactory]});
|
expect(pipes.config).toEqual({'pipe': AnotherPipe, 'pipe1': APipe, 'pipe2': AnotherPipe});
|
||||||
var binding = Pipes.extend({'async':<PipeFactory[]>[secondPipeFactory]});
|
|
||||||
var pipes: Pipes = binding.toFactory(originalPipes);
|
|
||||||
|
|
||||||
expect(pipes.config['async'].length).toBe(2);
|
|
||||||
expect(originalPipes.config['async'].length).toBe(1);
|
|
||||||
expect(pipes.get('async', 'second plz')).toBe(secondPipe);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if calling extend when creating root injector', () => {
|
it('should throw if calling extend when creating root injector', () => {
|
||||||
secondPipeFactory.spy("supports").andReturn(true);
|
var injector = Injector.resolveAndCreate([Pipes.extend({'pipe': APipe})]);
|
||||||
secondPipeFactory.spy("create").andReturn(secondPipe);
|
|
||||||
|
|
||||||
var injector: Injector =
|
|
||||||
Injector.resolveAndCreate([Pipes.extend({'async': [secondPipeFactory]})]);
|
|
||||||
|
|
||||||
expect(() => injector.get(Pipes))
|
expect(() => injector.get(Pipes))
|
||||||
.toThrowErrorWith("Cannot extend Pipes without a parent injector");
|
.toThrowErrorWith("Cannot extend Pipes without a parent injector");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should extend di-inherited pipes', () => {
|
|
||||||
firstPipeFactory.spy("supports").andReturn(true);
|
|
||||||
firstPipeFactory.spy("create").andReturn(firstPipe);
|
|
||||||
|
|
||||||
secondPipeFactory.spy("supports").andReturn(false);
|
|
||||||
|
|
||||||
var originalPipes: Pipes = new Pipes({'async': [firstPipeFactory]});
|
|
||||||
var injector: Injector = Injector.resolveAndCreate([bind(Pipes).toValue(originalPipes)]);
|
|
||||||
var childInjector: Injector =
|
|
||||||
injector.resolveAndCreateChild([Pipes.extend({'async': [secondPipeFactory]})]);
|
|
||||||
|
|
||||||
var parentPipes: Pipes = injector.get(Pipes);
|
|
||||||
var childPipes: Pipes = childInjector.get(Pipes);
|
|
||||||
|
|
||||||
expect(childPipes.config['async'].length).toBe(2);
|
|
||||||
expect(parentPipes.config['async'].length).toBe(1);
|
|
||||||
expect(childPipes.get('async', 'second plz')).toBe(firstPipe);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,27 +4,16 @@ import {UpperCasePipe} from 'angular2/src/change_detection/pipes/uppercase_pipe'
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
describe("UpperCasePipe", () => {
|
describe("UpperCasePipe", () => {
|
||||||
var str;
|
|
||||||
var upper;
|
var upper;
|
||||||
var lower;
|
var lower;
|
||||||
var pipe;
|
var pipe;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
str = 'something';
|
|
||||||
lower = 'something';
|
lower = 'something';
|
||||||
upper = 'SOMETHING';
|
upper = 'SOMETHING';
|
||||||
pipe = new UpperCasePipe();
|
pipe = new UpperCasePipe();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("supports", () => {
|
|
||||||
it("should support strings", () => { expect(pipe.supports(str)).toBe(true); });
|
|
||||||
|
|
||||||
it("should not support other objects", () => {
|
|
||||||
expect(pipe.supports(new Object())).toBe(false);
|
|
||||||
expect(pipe.supports(null)).toBe(false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("transform", () => {
|
describe("transform", () => {
|
||||||
|
|
||||||
it("should return uppercase", () => {
|
it("should return uppercase", () => {
|
||||||
|
@ -39,6 +28,8 @@ export function main() {
|
||||||
expect(val2).toEqual('WAT');
|
expect(val2).toEqual('WAT');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should not support other objects",
|
||||||
|
() => { expect(() => pipe.transform(new Object())).toThrowError(); });
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -35,7 +35,13 @@ import {
|
||||||
CONST,
|
CONST,
|
||||||
CONST_EXPR
|
CONST_EXPR
|
||||||
} from 'angular2/src/facade/lang';
|
} from 'angular2/src/facade/lang';
|
||||||
import {PromiseWrapper, EventEmitter, ObservableWrapper} from 'angular2/src/facade/async';
|
import {
|
||||||
|
PromiseWrapper,
|
||||||
|
EventEmitter,
|
||||||
|
ObservableWrapper,
|
||||||
|
PromiseCompleter,
|
||||||
|
Promise
|
||||||
|
} from 'angular2/src/facade/async';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Injector,
|
Injector,
|
||||||
|
@ -50,7 +56,6 @@ import {
|
||||||
SkipSelfMetadata
|
SkipSelfMetadata
|
||||||
} from 'angular2/di';
|
} from 'angular2/di';
|
||||||
import {
|
import {
|
||||||
PipeFactory,
|
|
||||||
Pipes,
|
Pipes,
|
||||||
defaultPipes,
|
defaultPipes,
|
||||||
Pipe,
|
Pipe,
|
||||||
|
@ -673,6 +678,34 @@ export function main() {
|
||||||
|
|
||||||
async.done();
|
async.done();
|
||||||
})}));
|
})}));
|
||||||
|
|
||||||
|
if (DOM.supportsDOMEvents()) {
|
||||||
|
it('should be checked when an async pipe requests a check',
|
||||||
|
inject([TestComponentBuilder], fakeAsync((tcb: TestComponentBuilder) => {
|
||||||
|
tcb = tcb.overrideView(MyComp, new viewAnn.View({
|
||||||
|
template: '<push-cmp-with-async #cmp></push-cmp-with-async>',
|
||||||
|
directives: [[[PushCmpWithAsyncPipe]]]
|
||||||
|
}));
|
||||||
|
|
||||||
|
var rootTC;
|
||||||
|
tcb.createAsync(MyComp).then(root => { rootTC = root; });
|
||||||
|
tick();
|
||||||
|
|
||||||
|
var cmp = rootTC.componentViewChildren[0].getLocal('cmp');
|
||||||
|
rootTC.detectChanges();
|
||||||
|
expect(cmp.numberOfChecks).toEqual(1);
|
||||||
|
|
||||||
|
rootTC.detectChanges();
|
||||||
|
rootTC.detectChanges();
|
||||||
|
expect(cmp.numberOfChecks).toEqual(1);
|
||||||
|
|
||||||
|
cmp.resolve(2);
|
||||||
|
tick();
|
||||||
|
|
||||||
|
rootTC.detectChanges();
|
||||||
|
expect(cmp.numberOfChecks).toEqual(2);
|
||||||
|
})));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create a component that injects an @Host',
|
it('should create a component that injects an @Host',
|
||||||
|
@ -1607,9 +1640,30 @@ class PushCmpWithRef {
|
||||||
propagate() { this.ref.requestCheck(); }
|
propagate() { this.ref.requestCheck(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Component({selector: 'push-cmp-with-async', changeDetection: ON_PUSH})
|
||||||
|
@View({template: '{{field | async}}'})
|
||||||
|
@Injectable()
|
||||||
|
class PushCmpWithAsyncPipe {
|
||||||
|
numberOfChecks: number = 0;
|
||||||
|
promise: Promise<any>;
|
||||||
|
completer: PromiseCompleter<any>;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.completer = PromiseWrapper.completer();
|
||||||
|
this.promise = this.completer.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
get field() {
|
||||||
|
this.numberOfChecks++;
|
||||||
|
return this.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(value) { this.completer.resolve(value); }
|
||||||
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
class PipesWithDouble extends Pipes {
|
class PipesWithDouble extends Pipes {
|
||||||
constructor() { super({"double": [new DoublePipeFactory()]}); }
|
constructor(injector: Injector) { super({"double": DoublePipe}, injector); }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -1703,19 +1757,9 @@ class SomeViewport {
|
||||||
@Injectable()
|
@Injectable()
|
||||||
class DoublePipe implements Pipe {
|
class DoublePipe implements Pipe {
|
||||||
onDestroy() {}
|
onDestroy() {}
|
||||||
|
|
||||||
supports(obj) { return true; }
|
|
||||||
|
|
||||||
transform(value, args = null) { return `${value}${value}`; }
|
transform(value, args = null) { return `${value}${value}`; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
class DoublePipeFactory implements PipeFactory {
|
|
||||||
supports(obj) { return true; }
|
|
||||||
|
|
||||||
create(cdRef) { return new DoublePipe(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Directive({selector: '[emitter]', events: ['event']})
|
@Directive({selector: '[emitter]', events: ['event']})
|
||||||
@Injectable()
|
@Injectable()
|
||||||
class DirectiveEmitingEvent {
|
class DirectiveEmitingEvent {
|
||||||
|
|
Loading…
Reference in New Issue