feat(pipe): added the Pipe decorator and the pipe property to View
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
This commit is contained in:
parent
02b7e61ef7
commit
5b5d31fa9a
@ -12,6 +12,7 @@
|
|||||||
export {
|
export {
|
||||||
ComponentAnnotation,
|
ComponentAnnotation,
|
||||||
DirectiveAnnotation,
|
DirectiveAnnotation,
|
||||||
|
PipeAnnotation,
|
||||||
LifecycleEvent
|
LifecycleEvent
|
||||||
} from './src/core/annotations/annotations';
|
} from './src/core/annotations/annotations';
|
||||||
|
|
||||||
@ -43,5 +44,7 @@ export {
|
|||||||
ViewFactory,
|
ViewFactory,
|
||||||
Query,
|
Query,
|
||||||
QueryFactory,
|
QueryFactory,
|
||||||
ViewQuery
|
ViewQuery,
|
||||||
|
Pipe,
|
||||||
|
PipeFactory
|
||||||
} from 'angular2/src/core/annotations/decorators';
|
} from 'angular2/src/core/annotations/decorators';
|
||||||
|
@ -20,14 +20,12 @@ export {
|
|||||||
ChangeDetectorRef,
|
ChangeDetectorRef,
|
||||||
|
|
||||||
WrappedValue,
|
WrappedValue,
|
||||||
defaultPipes,
|
PipeTransform,
|
||||||
Pipe,
|
|
||||||
Pipes,
|
|
||||||
IterableDiffers,
|
IterableDiffers,
|
||||||
IterableDiffer,
|
IterableDiffer,
|
||||||
IterableDifferFactory,
|
IterableDifferFactory,
|
||||||
KeyValueDiffers,
|
KeyValueDiffers,
|
||||||
KeyValueDiffer,
|
KeyValueDiffer,
|
||||||
KeyValueDifferFactory,
|
KeyValueDifferFactory,
|
||||||
BasePipe
|
BasePipeTransform
|
||||||
} from 'angular2/src/change_detection/change_detection';
|
} from 'angular2/src/change_detection/change_detection';
|
||||||
|
@ -4,10 +4,11 @@
|
|||||||
* This module provides advanced support for extending change detection.
|
* This module provides advanced support for extending change detection.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export {UpperCasePipe} from './src/change_detection/pipes/uppercase_pipe';
|
export {UpperCasePipe} from './src/pipes/uppercase_pipe';
|
||||||
export {LowerCasePipe} from './src/change_detection/pipes/lowercase_pipe';
|
export {LowerCasePipe} from './src/pipes/lowercase_pipe';
|
||||||
export {AsyncPipe} from './src/change_detection/pipes/async_pipe';
|
export {AsyncPipe} from './src/pipes/async_pipe';
|
||||||
export {JsonPipe} from './src/change_detection/pipes/json_pipe';
|
export {JsonPipe} from './src/pipes/json_pipe';
|
||||||
export {DatePipe} from './src/change_detection/pipes/date_pipe';
|
export {DatePipe} from './src/pipes/date_pipe';
|
||||||
export {DecimalPipe, PercentPipe, CurrencyPipe} from './src/change_detection/pipes/number_pipe';
|
export {DecimalPipe, PercentPipe, CurrencyPipe} from './src/pipes/number_pipe';
|
||||||
export {LimitToPipe} from './src/change_detection/pipes/limit_to_pipe';
|
export {LimitToPipe} from './src/pipes/limit_to_pipe';
|
||||||
|
export {DEFAULT_PIPES_TOKEN, DEFAULT_PIPES} from './src/pipes/default_pipes';
|
||||||
|
@ -4,6 +4,7 @@ import {ChangeDetectionUtil} from './change_detection_util';
|
|||||||
import {ChangeDetectorRef} from './change_detector_ref';
|
import {ChangeDetectorRef} from './change_detector_ref';
|
||||||
import {DirectiveRecord} from './directive_record';
|
import {DirectiveRecord} from './directive_record';
|
||||||
import {ChangeDetector, ChangeDispatcher} from './interfaces';
|
import {ChangeDetector, ChangeDispatcher} from './interfaces';
|
||||||
|
import {Pipes} from './pipes';
|
||||||
import {
|
import {
|
||||||
ChangeDetectionError,
|
ChangeDetectionError,
|
||||||
ExpressionChangedAfterItHasBeenCheckedException,
|
ExpressionChangedAfterItHasBeenCheckedException,
|
||||||
@ -12,7 +13,6 @@ import {
|
|||||||
import {ProtoRecord} from './proto_record';
|
import {ProtoRecord} from './proto_record';
|
||||||
import {BindingRecord} from './binding_record';
|
import {BindingRecord} from './binding_record';
|
||||||
import {Locals} from './parser/locals';
|
import {Locals} from './parser/locals';
|
||||||
import {Pipes} from './pipes/pipes';
|
|
||||||
import {CHECK_ALWAYS, CHECK_ONCE, CHECKED, DETACHED, ON_PUSH} from './constants';
|
import {CHECK_ALWAYS, CHECK_ONCE, CHECKED, DETACHED, ON_PUSH} from './constants';
|
||||||
import {wtfCreateScope, wtfLeave, WtfScopeFn} from '../profile/profile';
|
import {wtfCreateScope, wtfLeave, WtfScopeFn} from '../profile/profile';
|
||||||
|
|
||||||
|
@ -1,18 +1,10 @@
|
|||||||
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 {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 {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 {ChangeDetection, ProtoChangeDetector, ChangeDetectorDefinition} from './interfaces';
|
||||||
import {Injector, Inject, Injectable, OpaqueToken, Optional, Binding} 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';
|
||||||
@ -50,30 +42,10 @@ export {BindingRecord} from './binding_record';
|
|||||||
export {DirectiveIndex, DirectiveRecord} from './directive_record';
|
export {DirectiveIndex, DirectiveRecord} from './directive_record';
|
||||||
export {DynamicChangeDetector} from './dynamic_change_detector';
|
export {DynamicChangeDetector} from './dynamic_change_detector';
|
||||||
export {ChangeDetectorRef} from './change_detector_ref';
|
export {ChangeDetectorRef} from './change_detector_ref';
|
||||||
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, BasePipe} from './pipes/pipe';
|
export {PipeTransform, BasePipeTransform} from './pipe_transform';
|
||||||
|
export {WrappedValue} from './change_detection_util';
|
||||||
|
|
||||||
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.
|
||||||
|
@ -179,12 +179,10 @@ export class ChangeDetectorJITGenerator {
|
|||||||
var newValue = this._names.getLocalName(r.selfIndex);
|
var newValue = this._names.getLocalName(r.selfIndex);
|
||||||
|
|
||||||
var pipe = this._names.getPipeName(r.selfIndex);
|
var pipe = this._names.getPipeName(r.selfIndex);
|
||||||
var cdRef = "this.ref";
|
|
||||||
var pipeType = r.name;
|
var pipeType = r.name;
|
||||||
|
|
||||||
var read = `
|
var read = `
|
||||||
if (${pipe} === ${UTIL}.uninitialized) {
|
if (${pipe} === ${UTIL}.uninitialized) {
|
||||||
${pipe} = ${this._names.getPipesAccessorName()}.get('${pipeType}', ${cdRef});
|
${pipe} = ${this._names.getPipesAccessorName()}.get('${pipeType}');
|
||||||
}
|
}
|
||||||
${newValue} = ${pipe}.transform(${context}, [${argString}]);
|
${newValue} = ${pipe}.transform(${context}, [${argString}]);
|
||||||
`;
|
`;
|
||||||
|
@ -1,9 +1,47 @@
|
|||||||
import {CONST_EXPR, isPresent, isBlank, BaseException, Type} from 'angular2/src/facade/lang';
|
import {CONST_EXPR, isPresent, isBlank, BaseException, Type} from 'angular2/src/facade/lang';
|
||||||
import {List, ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
import {List, ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||||
import {ProtoRecord} from './proto_record';
|
import {ProtoRecord} from './proto_record';
|
||||||
import {WrappedValue} from './pipes/pipe';
|
|
||||||
import {CHECK_ALWAYS, CHECK_ONCE, CHECKED, DETACHED, ON_PUSH} from './constants';
|
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 {
|
export class SimpleChange {
|
||||||
constructor(public previousValue: any, public currentValue: any) {}
|
constructor(public previousValue: any, public currentValue: any) {}
|
||||||
|
|
||||||
|
@ -269,7 +269,7 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
|
|||||||
var storedPipe = this._readPipe(proto);
|
var storedPipe = this._readPipe(proto);
|
||||||
if (isPresent(storedPipe)) return storedPipe;
|
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);
|
this._writePipe(proto, pipe);
|
||||||
return pipe;
|
return pipe;
|
||||||
}
|
}
|
||||||
|
45
modules/angular2/src/change_detection/pipe_transform.ts
Normal file
45
modules/angular2/src/change_detection/pipe_transform.ts
Normal file
@ -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
modules/angular2/src/change_detection/pipes.ts
Normal file
3
modules/angular2/src/change_detection/pipes.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import {PipeTransform} from './pipe_transform';
|
||||||
|
|
||||||
|
export interface Pipes { get(name: string): PipeTransform; }
|
@ -1,84 +0,0 @@
|
|||||||
import {ABSTRACT, BaseException, CONST, Type} from 'angular2/src/facade/lang';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An interface which all pipes must implement.
|
|
||||||
*
|
|
||||||
* #Example
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* class DoublePipe implements Pipe {
|
|
||||||
* supports(obj) {
|
|
||||||
* return true;
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* onDestroy() {}
|
|
||||||
*
|
|
||||||
* transform(value, args = []) {
|
|
||||||
* return `${value}${value}`;
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
export interface Pipe {
|
|
||||||
/**
|
|
||||||
* Query if a pipe supports a particular object instance.
|
|
||||||
*/
|
|
||||||
onDestroy(): void;
|
|
||||||
|
|
||||||
transform(value: any, args: List<any>): any;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides default implementation of `supports` and `onDestroy` method.
|
|
||||||
*
|
|
||||||
* #Example
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* class DoublePipe extends BasePipe {
|
|
||||||
* transform(value) {
|
|
||||||
* return `${value}${value}`;
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
@CONST()
|
|
||||||
export class BasePipe implements Pipe {
|
|
||||||
onDestroy(): void {}
|
|
||||||
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}'`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function _abstract() {
|
|
||||||
throw new BaseException('This method is abstract');
|
|
||||||
}
|
|
@ -1,84 +0,0 @@
|
|||||||
import {ListWrapper, isListLikeIterable, StringMapWrapper} from 'angular2/src/facade/collection';
|
|
||||||
import {isBlank, isPresent, BaseException, CONST, Type} from 'angular2/src/facade/lang';
|
|
||||||
import {Pipe} from './pipe';
|
|
||||||
import {Injectable, OptionalMetadata, SkipSelfMetadata, Binding, Injector, bind} from 'angular2/di';
|
|
||||||
import {ChangeDetectorRef} from '../change_detector_ref';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
@CONST()
|
|
||||||
export class Pipes {
|
|
||||||
/**
|
|
||||||
* Map of {@link Pipe} names to {@link Pipe} implementations.
|
|
||||||
*
|
|
||||||
* #Example
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* var pipesConfig = {
|
|
||||||
* 'json': JsonPipe
|
|
||||||
* }
|
|
||||||
* @Component({
|
|
||||||
* viewBindings: [
|
|
||||||
* bind(Pipes).toFactory(inj => new Pipes(pipesConfig, in), [Injector])
|
|
||||||
* ]
|
|
||||||
* })
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
config: StringMap<string, Type | Binding>;
|
|
||||||
|
|
||||||
constructor(config: StringMap<string, Type | Binding>, public injector: Injector) {
|
|
||||||
this.config = config;
|
|
||||||
}
|
|
||||||
|
|
||||||
get(type: string, cdRef: ChangeDetectorRef): Pipe {
|
|
||||||
var typeOrBinding = this.config[type];
|
|
||||||
if (isBlank(typeOrBinding)) {
|
|
||||||
throw new BaseException(`Cannot find pipe '${type}'.`);
|
|
||||||
}
|
|
||||||
// this is a temporary workaround and will be removed
|
|
||||||
return this.injector.resolveAndCreateChild([bind(ChangeDetectorRef).toValue(cdRef)])
|
|
||||||
.resolveAndInstantiate(typeOrBinding);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Takes a {@link Pipes} config object and returns a binding used to extend the
|
|
||||||
* inherited {@link Pipes} instance with the provided config and return a new
|
|
||||||
* {@link Pipes} instance.
|
|
||||||
*
|
|
||||||
* The provided config is merged with the {@link Pipes} instance.
|
|
||||||
*
|
|
||||||
* # Example
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* @Component({
|
|
||||||
* viewBindings: [
|
|
||||||
* Pipes.extend({
|
|
||||||
* 'bithdayFormat': BirthdayFormat
|
|
||||||
* })
|
|
||||||
* ]
|
|
||||||
* })
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
static extend(config: StringMap<string, Type | Binding>): Binding {
|
|
||||||
return new Binding(Pipes, {
|
|
||||||
toFactory: (pipes: Pipes, injector: Injector) => {
|
|
||||||
if (isBlank(pipes)) {
|
|
||||||
// Typically would occur when calling Pipe.extend inside of dependencies passed to
|
|
||||||
// bootstrap(), which would override default pipes instead of extending them.
|
|
||||||
throw new BaseException('Cannot extend Pipes without a parent injector');
|
|
||||||
}
|
|
||||||
return Pipes.create(config, injector, pipes);
|
|
||||||
},
|
|
||||||
// Dependency technically isn't optional, but we can provide a better error message this way.
|
|
||||||
deps: [[Pipes, new SkipSelfMetadata(), new OptionalMetadata()], Injector]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static create(config: StringMap<string, Type | Binding>, injector: Injector,
|
|
||||||
pipes: Pipes = null): Pipes {
|
|
||||||
if (isPresent(pipes)) {
|
|
||||||
return new Pipes(StringMapWrapper.merge(pipes.config, config), injector);
|
|
||||||
} else {
|
|
||||||
return new Pipes(config, injector);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,7 +16,7 @@ export 'package:angular2/src/change_detection/directive_record.dart'
|
|||||||
show DirectiveIndex, DirectiveRecord;
|
show DirectiveIndex, DirectiveRecord;
|
||||||
export 'package:angular2/src/change_detection/interfaces.dart'
|
export 'package:angular2/src/change_detection/interfaces.dart'
|
||||||
show ChangeDetector, ChangeDetectorDefinition, ProtoChangeDetector;
|
show ChangeDetector, ChangeDetectorDefinition, ProtoChangeDetector;
|
||||||
export 'package:angular2/src/change_detection/pipes/pipes.dart' show Pipes;
|
export 'package:angular2/src/change_detection/pipes.dart' show Pipes;
|
||||||
export 'package:angular2/src/change_detection/proto_record.dart'
|
export 'package:angular2/src/change_detection/proto_record.dart'
|
||||||
show ProtoRecord;
|
show ProtoRecord;
|
||||||
export 'package:angular2/src/change_detection/change_detection_util.dart'
|
export 'package:angular2/src/change_detection/change_detection_util.dart'
|
||||||
|
@ -6,5 +6,6 @@
|
|||||||
export {
|
export {
|
||||||
Component as ComponentAnnotation,
|
Component as ComponentAnnotation,
|
||||||
Directive as DirectiveAnnotation,
|
Directive as DirectiveAnnotation,
|
||||||
|
Pipe as PipeAnnotation,
|
||||||
LifecycleEvent
|
LifecycleEvent
|
||||||
} from '../annotations_impl/annotations';
|
} from '../annotations_impl/annotations';
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
import {ComponentAnnotation, DirectiveAnnotation, LifecycleEvent} from './annotations';
|
import {
|
||||||
|
ComponentAnnotation,
|
||||||
|
DirectiveAnnotation,
|
||||||
|
PipeAnnotation,
|
||||||
|
LifecycleEvent
|
||||||
|
} from './annotations';
|
||||||
import {ViewAnnotation} from './view';
|
import {ViewAnnotation} from './view';
|
||||||
import {AttributeAnnotation, QueryAnnotation, ViewQueryAnnotation} from './di';
|
import {AttributeAnnotation, QueryAnnotation, ViewQueryAnnotation} from './di';
|
||||||
import {makeDecorator, makeParamDecorator, TypeDecorator, Class} from '../../util/decorators';
|
import {makeDecorator, makeParamDecorator, TypeDecorator, Class} from '../../util/decorators';
|
||||||
@ -25,6 +30,7 @@ export interface ComponentDecorator extends TypeDecorator {
|
|||||||
templateUrl?: string,
|
templateUrl?: string,
|
||||||
template?: string,
|
template?: string,
|
||||||
directives?: List<Type | any | List<any>>,
|
directives?: List<Type | any | List<any>>,
|
||||||
|
pipes?: List<Type | any | List<any>>,
|
||||||
renderer?: string,
|
renderer?: string,
|
||||||
styles?: List<string>,
|
styles?: List<string>,
|
||||||
styleUrls?: List<string>,
|
styleUrls?: List<string>,
|
||||||
@ -44,6 +50,7 @@ export interface ViewDecorator extends TypeDecorator {
|
|||||||
templateUrl?: string,
|
templateUrl?: string,
|
||||||
template?: string,
|
template?: string,
|
||||||
directives?: List<Type | any | List<any>>,
|
directives?: List<Type | any | List<any>>,
|
||||||
|
pipes?: List<Type | any | List<any>>,
|
||||||
renderer?: string,
|
renderer?: string,
|
||||||
styles?: List<string>,
|
styles?: List<string>,
|
||||||
styleUrls?: List<string>,
|
styleUrls?: List<string>,
|
||||||
@ -337,6 +344,30 @@ export interface QueryFactory {
|
|||||||
new (selector: Type | string, {descendants}?: {descendants?: boolean}): QueryAnnotation;
|
new (selector: Type | string, {descendants}?: {descendants?: boolean}): QueryAnnotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Pipe} factory for creating decorators.
|
||||||
|
*
|
||||||
|
* ## Example as TypeScript Decorator
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* import {Pipe} from "angular2/angular2";
|
||||||
|
*
|
||||||
|
* @Pipe({...})
|
||||||
|
* class MyPipe {
|
||||||
|
* constructor() {
|
||||||
|
* ...
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* transform(v, args) {}
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export interface PipeFactory {
|
||||||
|
(obj: {name: string}): any;
|
||||||
|
new (obj: {
|
||||||
|
name: string,
|
||||||
|
}): any;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link Component} factory function.
|
* {@link Component} factory function.
|
||||||
@ -369,3 +400,8 @@ export var Query: QueryFactory = makeParamDecorator(QueryAnnotation);
|
|||||||
* {@link ViewQuery} factory function.
|
* {@link ViewQuery} factory function.
|
||||||
*/
|
*/
|
||||||
export var ViewQuery: QueryFactory = makeParamDecorator(ViewQueryAnnotation);
|
export var ViewQuery: QueryFactory = makeParamDecorator(ViewQueryAnnotation);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Pipe} factory function.
|
||||||
|
*/
|
||||||
|
export var Pipe: PipeFactory = <PipeFactory>makeDecorator(PipeAnnotation);
|
||||||
|
@ -1030,3 +1030,27 @@ export enum LifecycleEvent {
|
|||||||
*/
|
*/
|
||||||
onAllChangesDone
|
onAllChangesDone
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Declare reusable pipe function.
|
||||||
|
*
|
||||||
|
* ## Example
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* @Pipe({
|
||||||
|
* name: 'lowercase'
|
||||||
|
* })
|
||||||
|
* class Lowercase {
|
||||||
|
* transform(v, args) { return v.toLowerCase(); }
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
@CONST()
|
||||||
|
export class Pipe extends InjectableMetadata {
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
constructor({name}: {name: string}) {
|
||||||
|
super();
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -87,6 +87,8 @@ export class View {
|
|||||||
// for an unused import.
|
// for an unused import.
|
||||||
directives: List<Type | any | List<any>>;
|
directives: List<Type | any | List<any>>;
|
||||||
|
|
||||||
|
pipes: List<Type | any | List<any>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify how the template and the styles should be encapsulated.
|
* Specify how the template and the styles should be encapsulated.
|
||||||
* The default is {@link ViewEncapsulation#EMULATED `ViewEncapsulation.EMULATED`} if the view
|
* The default is {@link ViewEncapsulation#EMULATED `ViewEncapsulation.EMULATED`} if the view
|
||||||
@ -95,10 +97,11 @@ export class View {
|
|||||||
*/
|
*/
|
||||||
encapsulation: ViewEncapsulation;
|
encapsulation: ViewEncapsulation;
|
||||||
|
|
||||||
constructor({templateUrl, template, directives, encapsulation, styles, styleUrls}: {
|
constructor({templateUrl, template, directives, pipes, encapsulation, styles, styleUrls}: {
|
||||||
templateUrl?: string,
|
templateUrl?: string,
|
||||||
template?: string,
|
template?: string,
|
||||||
directives?: List<Type | any | List<any>>,
|
directives?: List<Type | any | List<any>>,
|
||||||
|
pipes?: List<Type | any | List<any>>,
|
||||||
encapsulation?: ViewEncapsulation,
|
encapsulation?: ViewEncapsulation,
|
||||||
styles?: List<string>,
|
styles?: List<string>,
|
||||||
styleUrls?: List<string>,
|
styleUrls?: List<string>,
|
||||||
@ -108,6 +111,7 @@ export class View {
|
|||||||
this.styleUrls = styleUrls;
|
this.styleUrls = styleUrls;
|
||||||
this.styles = styles;
|
this.styles = styles;
|
||||||
this.directives = directives;
|
this.directives = directives;
|
||||||
|
this.pipes = pipes;
|
||||||
this.encapsulation = encapsulation;
|
this.encapsulation = encapsulation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,19 +21,19 @@ import {
|
|||||||
DynamicChangeDetection,
|
DynamicChangeDetection,
|
||||||
JitChangeDetection,
|
JitChangeDetection,
|
||||||
PreGeneratedChangeDetection,
|
PreGeneratedChangeDetection,
|
||||||
Pipes,
|
|
||||||
defaultPipes,
|
|
||||||
IterableDiffers,
|
IterableDiffers,
|
||||||
defaultIterableDiffers,
|
defaultIterableDiffers,
|
||||||
KeyValueDiffers,
|
KeyValueDiffers,
|
||||||
defaultKeyValueDiffers
|
defaultKeyValueDiffers
|
||||||
} from 'angular2/src/change_detection/change_detection';
|
} from 'angular2/src/change_detection/change_detection';
|
||||||
|
import {DEFAULT_PIPES} from 'angular2/pipes';
|
||||||
import {ExceptionHandler} from './exception_handler';
|
import {ExceptionHandler} from './exception_handler';
|
||||||
import {ViewLoader} from 'angular2/src/render/dom/compiler/view_loader';
|
import {ViewLoader} from 'angular2/src/render/dom/compiler/view_loader';
|
||||||
import {StyleUrlResolver} from 'angular2/src/render/dom/compiler/style_url_resolver';
|
import {StyleUrlResolver} from 'angular2/src/render/dom/compiler/style_url_resolver';
|
||||||
import {StyleInliner} from 'angular2/src/render/dom/compiler/style_inliner';
|
import {StyleInliner} from 'angular2/src/render/dom/compiler/style_inliner';
|
||||||
import {ViewResolver} from './compiler/view_resolver';
|
import {ViewResolver} from './compiler/view_resolver';
|
||||||
import {DirectiveResolver} from './compiler/directive_resolver';
|
import {DirectiveResolver} from './compiler/directive_resolver';
|
||||||
|
import {PipeResolver} from './compiler/pipe_resolver';
|
||||||
import {List, ListWrapper} from 'angular2/src/facade/collection';
|
import {List, ListWrapper} from 'angular2/src/facade/collection';
|
||||||
import {Promise, PromiseWrapper, PromiseCompleter} from 'angular2/src/facade/async';
|
import {Promise, PromiseWrapper, PromiseCompleter} from 'angular2/src/facade/async';
|
||||||
import {NgZone} from 'angular2/src/core/zone/ng_zone';
|
import {NgZone} from 'angular2/src/core/zone/ng_zone';
|
||||||
@ -137,12 +137,13 @@ function _injectorBindings(appComponentType): List<Type | Binding | List<any>> {
|
|||||||
Compiler,
|
Compiler,
|
||||||
CompilerCache,
|
CompilerCache,
|
||||||
ViewResolver,
|
ViewResolver,
|
||||||
defaultPipes,
|
DEFAULT_PIPES,
|
||||||
bind(IterableDiffers).toValue(defaultIterableDiffers),
|
bind(IterableDiffers).toValue(defaultIterableDiffers),
|
||||||
bind(KeyValueDiffers).toValue(defaultKeyValueDiffers),
|
bind(KeyValueDiffers).toValue(defaultKeyValueDiffers),
|
||||||
bind(ChangeDetection).toClass(bestChangeDetection),
|
bind(ChangeDetection).toClass(bestChangeDetection),
|
||||||
ViewLoader,
|
ViewLoader,
|
||||||
DirectiveResolver,
|
DirectiveResolver,
|
||||||
|
PipeResolver,
|
||||||
Parser,
|
Parser,
|
||||||
Lexer,
|
Lexer,
|
||||||
bind(ExceptionHandler).toFactory(() => new ExceptionHandler(DOM, isDart ? false : true), []),
|
bind(ExceptionHandler).toFactory(() => new ExceptionHandler(DOM, isDart ? false : true), []),
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {Binding, resolveForwardRef, Injectable} from 'angular2/di';
|
import {Binding, resolveForwardRef, Injectable, Inject} from 'angular2/di';
|
||||||
import {
|
import {
|
||||||
Type,
|
Type,
|
||||||
isBlank,
|
isBlank,
|
||||||
@ -19,6 +19,7 @@ import {AppProtoView, AppProtoViewMergeMapping} from './view';
|
|||||||
import {ProtoViewRef} from './view_ref';
|
import {ProtoViewRef} from './view_ref';
|
||||||
import {DirectiveBinding} from './element_injector';
|
import {DirectiveBinding} from './element_injector';
|
||||||
import {ViewResolver} from './view_resolver';
|
import {ViewResolver} from './view_resolver';
|
||||||
|
import {PipeResolver} from './pipe_resolver';
|
||||||
import {View} from '../annotations_impl/view';
|
import {View} from '../annotations_impl/view';
|
||||||
import {ComponentUrlMapper} from './component_url_mapper';
|
import {ComponentUrlMapper} from './component_url_mapper';
|
||||||
import {ProtoViewFactory} from './proto_view_factory';
|
import {ProtoViewFactory} from './proto_view_factory';
|
||||||
@ -26,6 +27,8 @@ import {UrlResolver} from 'angular2/src/services/url_resolver';
|
|||||||
import {AppRootUrl} from 'angular2/src/services/app_root_url';
|
import {AppRootUrl} from 'angular2/src/services/app_root_url';
|
||||||
import {ElementBinder} from './element_binder';
|
import {ElementBinder} from './element_binder';
|
||||||
import {wtfStartTimeRange, wtfEndTimeRange} from '../../profile/profile';
|
import {wtfStartTimeRange, wtfEndTimeRange} from '../../profile/profile';
|
||||||
|
import {PipeBinding} from '../pipes/pipe_binding';
|
||||||
|
import {DEFAULT_PIPES_TOKEN} from 'angular2/pipes';
|
||||||
|
|
||||||
import * as renderApi from 'angular2/src/render/api';
|
import * as renderApi from 'angular2/src/render/api';
|
||||||
|
|
||||||
@ -83,46 +86,40 @@ export class CompilerCache {
|
|||||||
*/
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class Compiler {
|
export class Compiler {
|
||||||
private _reader: DirectiveResolver;
|
private _compiling: Map<Type, Promise<AppProtoView>> = new Map();
|
||||||
private _compilerCache: CompilerCache;
|
|
||||||
private _compiling: Map<Type, Promise<AppProtoView>>;
|
|
||||||
private _viewResolver: ViewResolver;
|
|
||||||
private _componentUrlMapper: ComponentUrlMapper;
|
|
||||||
private _urlResolver: UrlResolver;
|
|
||||||
private _appUrl: string;
|
private _appUrl: string;
|
||||||
private _render: renderApi.RenderCompiler;
|
private _defaultPipes: Type[];
|
||||||
private _protoViewFactory: ProtoViewFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
constructor(reader: DirectiveResolver, cache: CompilerCache, viewResolver: ViewResolver,
|
constructor(private _directiveResolver: DirectiveResolver, private _pipeResolver: PipeResolver,
|
||||||
componentUrlMapper: ComponentUrlMapper, urlResolver: UrlResolver,
|
@Inject(DEFAULT_PIPES_TOKEN) _defaultPipes: Type[],
|
||||||
render: renderApi.RenderCompiler, protoViewFactory: ProtoViewFactory,
|
private _compilerCache: CompilerCache, private _viewResolver: ViewResolver,
|
||||||
appUrl: AppRootUrl) {
|
private _componentUrlMapper: ComponentUrlMapper, private _urlResolver: UrlResolver,
|
||||||
this._reader = reader;
|
private _render: renderApi.RenderCompiler,
|
||||||
this._compilerCache = cache;
|
private _protoViewFactory: ProtoViewFactory, appUrl: AppRootUrl) {
|
||||||
this._compiling = new Map();
|
this._defaultPipes = _defaultPipes;
|
||||||
this._viewResolver = viewResolver;
|
|
||||||
this._componentUrlMapper = componentUrlMapper;
|
|
||||||
this._urlResolver = urlResolver;
|
|
||||||
this._appUrl = appUrl.value;
|
this._appUrl = appUrl.value;
|
||||||
this._render = render;
|
|
||||||
this._protoViewFactory = protoViewFactory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _bindDirective(directiveTypeOrBinding): DirectiveBinding {
|
private _bindDirective(directiveTypeOrBinding): DirectiveBinding {
|
||||||
if (directiveTypeOrBinding instanceof DirectiveBinding) {
|
if (directiveTypeOrBinding instanceof DirectiveBinding) {
|
||||||
return directiveTypeOrBinding;
|
return directiveTypeOrBinding;
|
||||||
} else if (directiveTypeOrBinding instanceof Binding) {
|
} else if (directiveTypeOrBinding instanceof Binding) {
|
||||||
let annotation = this._reader.resolve(directiveTypeOrBinding.token);
|
let annotation = this._directiveResolver.resolve(directiveTypeOrBinding.token);
|
||||||
return DirectiveBinding.createFromBinding(directiveTypeOrBinding, annotation);
|
return DirectiveBinding.createFromBinding(directiveTypeOrBinding, annotation);
|
||||||
} else {
|
} else {
|
||||||
let annotation = this._reader.resolve(directiveTypeOrBinding);
|
let annotation = this._directiveResolver.resolve(directiveTypeOrBinding);
|
||||||
return DirectiveBinding.createFromType(directiveTypeOrBinding, annotation);
|
return DirectiveBinding.createFromType(directiveTypeOrBinding, annotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _bindPipe(typeOrBinding): PipeBinding {
|
||||||
|
let meta = this._pipeResolver.resolve(typeOrBinding);
|
||||||
|
return PipeBinding.createFromType(typeOrBinding, meta);
|
||||||
|
}
|
||||||
|
|
||||||
// Create a hostView as if the compiler encountered <hostcmp></hostcmp>.
|
// Create a hostView as if the compiler encountered <hostcmp></hostcmp>.
|
||||||
// Used for bootstrapping.
|
// Used for bootstrapping.
|
||||||
compileInHost(componentTypeOrBinding: Type | Binding): Promise<ProtoViewRef> {
|
compileInHost(componentTypeOrBinding: Type | Binding): Promise<ProtoViewRef> {
|
||||||
@ -143,7 +140,7 @@ export class Compiler {
|
|||||||
this._render.compileHost(directiveMetadata)
|
this._render.compileHost(directiveMetadata)
|
||||||
.then((hostRenderPv) => {
|
.then((hostRenderPv) => {
|
||||||
var protoViews = this._protoViewFactory.createAppProtoViews(
|
var protoViews = this._protoViewFactory.createAppProtoViews(
|
||||||
componentBinding, hostRenderPv, [componentBinding]);
|
componentBinding, hostRenderPv, [componentBinding], []);
|
||||||
return this._compileNestedProtoViews(protoViews, componentType, new Map());
|
return this._compileNestedProtoViews(protoViews, componentType, new Map());
|
||||||
})
|
})
|
||||||
.then((appProtoView) => {
|
.then((appProtoView) => {
|
||||||
@ -186,14 +183,17 @@ export class Compiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var boundDirectives = this._removeDuplicatedDirectives(
|
var boundDirectives = this._removeDuplicatedDirectives(
|
||||||
ListWrapper.map(directives, (directive) => this._bindDirective(directive)));
|
directives.map(directive => this._bindDirective(directive)));
|
||||||
|
|
||||||
|
var pipes = this._flattenPipes(view);
|
||||||
|
var boundPipes = pipes.map(pipe => this._bindPipe(pipe));
|
||||||
|
|
||||||
var renderTemplate = this._buildRenderTemplate(component, view, boundDirectives);
|
var renderTemplate = this._buildRenderTemplate(component, view, boundDirectives);
|
||||||
resultPromise =
|
resultPromise =
|
||||||
this._render.compile(renderTemplate)
|
this._render.compile(renderTemplate)
|
||||||
.then((renderPv) => {
|
.then((renderPv) => {
|
||||||
var protoViews = this._protoViewFactory.createAppProtoViews(
|
var protoViews = this._protoViewFactory.createAppProtoViews(
|
||||||
componentBinding, renderPv, boundDirectives);
|
componentBinding, renderPv, boundDirectives, boundPipes);
|
||||||
return this._compileNestedProtoViews(protoViews, component, componentPath);
|
return this._compileNestedProtoViews(protoViews, component, componentPath);
|
||||||
})
|
})
|
||||||
.then((appProtoView) => {
|
.then((appProtoView) => {
|
||||||
@ -317,12 +317,17 @@ export class Compiler {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private _flattenDirectives(template: View): List<Type> {
|
private _flattenPipes(view: View): any[] {
|
||||||
if (isBlank(template.directives)) return [];
|
if (isBlank(view.pipes)) return this._defaultPipes;
|
||||||
|
var pipes = ListWrapper.clone(this._defaultPipes);
|
||||||
|
this._flattenList(view.pipes, pipes);
|
||||||
|
return pipes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _flattenDirectives(view: View): List<Type> {
|
||||||
|
if (isBlank(view.directives)) return [];
|
||||||
var directives = [];
|
var directives = [];
|
||||||
this._flattenList(template.directives, directives);
|
this._flattenList(view.directives, directives);
|
||||||
|
|
||||||
return directives;
|
return directives;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,14 +42,11 @@ import {ElementRef} from './element_ref';
|
|||||||
import {TemplateRef} from './template_ref';
|
import {TemplateRef} from './template_ref';
|
||||||
import {Directive, Component, LifecycleEvent} from 'angular2/src/core/annotations_impl/annotations';
|
import {Directive, Component, LifecycleEvent} from 'angular2/src/core/annotations_impl/annotations';
|
||||||
import {hasLifecycleHook} from './directive_lifecycle_reflector';
|
import {hasLifecycleHook} from './directive_lifecycle_reflector';
|
||||||
import {
|
import {ChangeDetector, ChangeDetectorRef} from 'angular2/src/change_detection/change_detection';
|
||||||
ChangeDetector,
|
|
||||||
ChangeDetectorRef,
|
|
||||||
Pipes
|
|
||||||
} from 'angular2/src/change_detection/change_detection';
|
|
||||||
import {QueryList} from './query_list';
|
import {QueryList} from './query_list';
|
||||||
import {reflector} from 'angular2/src/reflection/reflection';
|
import {reflector} from 'angular2/src/reflection/reflection';
|
||||||
import {DirectiveMetadata} from 'angular2/src/render/api';
|
import {DirectiveMetadata} from 'angular2/src/render/api';
|
||||||
|
import {PipeBinding} from '../pipes/pipe_binding';
|
||||||
|
|
||||||
var _staticKeys;
|
var _staticKeys;
|
||||||
|
|
||||||
@ -59,7 +56,6 @@ export class StaticKeys {
|
|||||||
viewContainerId: number;
|
viewContainerId: number;
|
||||||
changeDetectorRefId: number;
|
changeDetectorRefId: number;
|
||||||
elementRefId: number;
|
elementRefId: number;
|
||||||
pipesKey: Key;
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.viewManagerId = Key.get(avmModule.AppViewManager).id;
|
this.viewManagerId = Key.get(avmModule.AppViewManager).id;
|
||||||
@ -67,8 +63,6 @@ export class StaticKeys {
|
|||||||
this.viewContainerId = Key.get(ViewContainerRef).id;
|
this.viewContainerId = Key.get(ViewContainerRef).id;
|
||||||
this.changeDetectorRefId = Key.get(ChangeDetectorRef).id;
|
this.changeDetectorRefId = Key.get(ChangeDetectorRef).id;
|
||||||
this.elementRefId = Key.get(ElementRef).id;
|
this.elementRefId = Key.get(ElementRef).id;
|
||||||
// not an id because the public API of injector works only with keys and tokens
|
|
||||||
this.pipesKey = Key.get(Pipes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static instance(): StaticKeys {
|
static instance(): StaticKeys {
|
||||||
@ -541,11 +535,6 @@ export class ElementInjector extends TreeNode<ElementInjector> implements Depend
|
|||||||
injector.internalStrategy.attach(parentInjector, isBoundary);
|
injector.internalStrategy.attach(parentInjector, isBoundary);
|
||||||
}
|
}
|
||||||
|
|
||||||
getPipes(): Pipes {
|
|
||||||
var pipesKey = StaticKeys.instance().pipesKey;
|
|
||||||
return this._injector.getOptional(pipesKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
hasVariableBinding(name: string): boolean {
|
hasVariableBinding(name: string): boolean {
|
||||||
var vb = this._proto.directiveVariableBindings;
|
var vb = this._proto.directiveVariableBindings;
|
||||||
return isPresent(vb) && vb.has(name);
|
return isPresent(vb) && vb.has(name);
|
||||||
@ -589,51 +578,57 @@ export class ElementInjector extends TreeNode<ElementInjector> implements Depend
|
|||||||
getDependency(injector: Injector, binding: ResolvedBinding, dep: Dependency): any {
|
getDependency(injector: Injector, binding: ResolvedBinding, dep: Dependency): any {
|
||||||
var key: Key = dep.key;
|
var key: Key = dep.key;
|
||||||
|
|
||||||
if (!(dep instanceof DirectiveDependency)) return undefinedValue;
|
if (binding instanceof DirectiveBinding) {
|
||||||
if (!(binding instanceof DirectiveBinding)) return undefinedValue;
|
var dirDep = <DirectiveDependency>dep;
|
||||||
|
var dirBin = binding;
|
||||||
var dirDep = <DirectiveDependency>dep;
|
var staticKeys = StaticKeys.instance();
|
||||||
var dirBin = <DirectiveBinding>binding;
|
|
||||||
var staticKeys = StaticKeys.instance();
|
|
||||||
|
|
||||||
|
|
||||||
if (key.id === staticKeys.viewManagerId) return this._preBuiltObjects.viewManager;
|
if (key.id === staticKeys.viewManagerId) return this._preBuiltObjects.viewManager;
|
||||||
|
|
||||||
if (isPresent(dirDep.attributeName)) return this._buildAttribute(dirDep);
|
if (isPresent(dirDep.attributeName)) return this._buildAttribute(dirDep);
|
||||||
|
|
||||||
if (isPresent(dirDep.queryDecorator)) return this._findQuery(dirDep.queryDecorator).list;
|
if (isPresent(dirDep.queryDecorator)) return this._findQuery(dirDep.queryDecorator).list;
|
||||||
|
|
||||||
if (dirDep.key.id === StaticKeys.instance().changeDetectorRefId) {
|
if (dirDep.key.id === StaticKeys.instance().changeDetectorRefId) {
|
||||||
// We provide the component's view change detector to components and
|
// We provide the component's view change detector to components and
|
||||||
// the surrounding component's change detector to directives.
|
// the surrounding component's change detector to directives.
|
||||||
if (dirBin.metadata.type === DirectiveMetadata.COMPONENT_TYPE) {
|
if (dirBin.metadata.type === DirectiveMetadata.COMPONENT_TYPE) {
|
||||||
|
var componentView = this._preBuiltObjects.view.getNestedView(
|
||||||
|
this._preBuiltObjects.elementRef.boundElementIndex);
|
||||||
|
return componentView.changeDetector.ref;
|
||||||
|
} else {
|
||||||
|
return this._preBuiltObjects.view.changeDetector.ref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dirDep.key.id === StaticKeys.instance().elementRefId) {
|
||||||
|
return this.getElementRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dirDep.key.id === StaticKeys.instance().viewContainerId) {
|
||||||
|
return this.getViewContainerRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dirDep.key.id === StaticKeys.instance().templateRefId) {
|
||||||
|
if (isBlank(this._preBuiltObjects.templateRef)) {
|
||||||
|
if (dirDep.optional) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new NoBindingError(null, dirDep.key);
|
||||||
|
}
|
||||||
|
return this._preBuiltObjects.templateRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (binding instanceof PipeBinding) {
|
||||||
|
if (dep.key.id === StaticKeys.instance().changeDetectorRefId) {
|
||||||
var componentView = this._preBuiltObjects.view.getNestedView(
|
var componentView = this._preBuiltObjects.view.getNestedView(
|
||||||
this._preBuiltObjects.elementRef.boundElementIndex);
|
this._preBuiltObjects.elementRef.boundElementIndex);
|
||||||
return componentView.changeDetector.ref;
|
return componentView.changeDetector.ref;
|
||||||
} else {
|
|
||||||
return this._preBuiltObjects.view.changeDetector.ref;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dirDep.key.id === StaticKeys.instance().elementRefId) {
|
|
||||||
return this.getElementRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dirDep.key.id === StaticKeys.instance().viewContainerId) {
|
|
||||||
return this.getViewContainerRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dirDep.key.id === StaticKeys.instance().templateRefId) {
|
|
||||||
if (isBlank(this._preBuiltObjects.templateRef)) {
|
|
||||||
if (dirDep.optional) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new NoBindingError(null, dirDep.key);
|
|
||||||
}
|
|
||||||
return this._preBuiltObjects.templateRef;
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefinedValue;
|
return undefinedValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
30
modules/angular2/src/core/compiler/pipe_resolver.ts
Normal file
30
modules/angular2/src/core/compiler/pipe_resolver.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import {resolveForwardRef, Injectable} from 'angular2/di';
|
||||||
|
import {Type, isPresent, BaseException, stringify} from 'angular2/src/facade/lang';
|
||||||
|
import {Pipe} from '../annotations_impl/annotations';
|
||||||
|
import {reflector} from 'angular2/src/reflection/reflection';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve a `Type` for {@link Pipe}.
|
||||||
|
*
|
||||||
|
* This interface can be overridden by the application developer to create custom behavior.
|
||||||
|
*
|
||||||
|
* See {@link Compiler}
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class PipeResolver {
|
||||||
|
/**
|
||||||
|
* Return {@link Pipe} for a given `Type`.
|
||||||
|
*/
|
||||||
|
resolve(type: Type): Pipe {
|
||||||
|
var metas = reflector.annotations(resolveForwardRef(type));
|
||||||
|
if (isPresent(metas)) {
|
||||||
|
for (var i = 0; i < metas.length; i++) {
|
||||||
|
var annotation = metas[i];
|
||||||
|
if (annotation instanceof Pipe) {
|
||||||
|
return annotation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new BaseException(`No Pipe decorator found on ${stringify(type)}`);
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,9 @@ import {
|
|||||||
ASTWithSource
|
ASTWithSource
|
||||||
} from 'angular2/src/change_detection/change_detection';
|
} from 'angular2/src/change_detection/change_detection';
|
||||||
|
|
||||||
|
import {PipeBinding} from 'angular2/src/core/pipes/pipe_binding';
|
||||||
|
import {ProtoPipes} from 'angular2/src/core/pipes/pipes';
|
||||||
|
|
||||||
import * as renderApi from 'angular2/src/render/api';
|
import * as renderApi from 'angular2/src/render/api';
|
||||||
import {AppProtoView} from './view';
|
import {AppProtoView} from './view';
|
||||||
import {ElementBinder} from './element_binder';
|
import {ElementBinder} from './element_binder';
|
||||||
@ -160,7 +163,7 @@ export class ProtoViewFactory {
|
|||||||
|
|
||||||
createAppProtoViews(hostComponentBinding: DirectiveBinding,
|
createAppProtoViews(hostComponentBinding: DirectiveBinding,
|
||||||
rootRenderProtoView: renderApi.ProtoViewDto,
|
rootRenderProtoView: renderApi.ProtoViewDto,
|
||||||
allDirectives: List<DirectiveBinding>): AppProtoView[] {
|
allDirectives: List<DirectiveBinding>, pipes: PipeBinding[]): AppProtoView[] {
|
||||||
var allRenderDirectiveMetadata =
|
var allRenderDirectiveMetadata =
|
||||||
ListWrapper.map(allDirectives, directiveBinding => directiveBinding.metadata);
|
ListWrapper.map(allDirectives, directiveBinding => directiveBinding.metadata);
|
||||||
var nestedPvsWithIndex = _collectNestedProtoViews(rootRenderProtoView);
|
var nestedPvsWithIndex = _collectNestedProtoViews(rootRenderProtoView);
|
||||||
@ -177,7 +180,7 @@ export class ProtoViewFactory {
|
|||||||
ListWrapper.forEach(nestedPvsWithIndex, (pvWithIndex: RenderProtoViewWithIndex) => {
|
ListWrapper.forEach(nestedPvsWithIndex, (pvWithIndex: RenderProtoViewWithIndex) => {
|
||||||
var appProtoView =
|
var appProtoView =
|
||||||
_createAppProtoView(pvWithIndex.renderProtoView, protoChangeDetectors[pvWithIndex.index],
|
_createAppProtoView(pvWithIndex.renderProtoView, protoChangeDetectors[pvWithIndex.index],
|
||||||
nestedPvVariableBindings[pvWithIndex.index], allDirectives);
|
nestedPvVariableBindings[pvWithIndex.index], allDirectives, pipes);
|
||||||
if (isPresent(pvWithIndex.parentIndex)) {
|
if (isPresent(pvWithIndex.parentIndex)) {
|
||||||
var parentView = appProtoViews[pvWithIndex.parentIndex];
|
var parentView = appProtoViews[pvWithIndex.parentIndex];
|
||||||
parentView.elementBinders[pvWithIndex.boundElementIndex].nestedProtoView = appProtoView;
|
parentView.elementBinders[pvWithIndex.boundElementIndex].nestedProtoView = appProtoView;
|
||||||
@ -252,14 +255,16 @@ function _getChangeDetectorDefinitions(
|
|||||||
|
|
||||||
function _createAppProtoView(
|
function _createAppProtoView(
|
||||||
renderProtoView: renderApi.ProtoViewDto, protoChangeDetector: ProtoChangeDetector,
|
renderProtoView: renderApi.ProtoViewDto, protoChangeDetector: ProtoChangeDetector,
|
||||||
variableBindings: Map<string, string>, allDirectives: List<DirectiveBinding>): AppProtoView {
|
variableBindings: Map<string, string>, allDirectives: List<DirectiveBinding>,
|
||||||
|
pipes: PipeBinding[]): AppProtoView {
|
||||||
var elementBinders = renderProtoView.elementBinders;
|
var elementBinders = renderProtoView.elementBinders;
|
||||||
// Embedded ProtoViews that contain `<ng-content>` will be merged into their parents and use
|
// Embedded ProtoViews that contain `<ng-content>` will be merged into their parents and use
|
||||||
// a RenderFragmentRef. I.e. renderProtoView.transitiveNgContentCount > 0.
|
// a RenderFragmentRef. I.e. renderProtoView.transitiveNgContentCount > 0.
|
||||||
|
var protoPipes = new ProtoPipes(pipes);
|
||||||
var protoView = new AppProtoView(
|
var protoView = new AppProtoView(
|
||||||
renderProtoView.type, renderProtoView.transitiveNgContentCount > 0, renderProtoView.render,
|
renderProtoView.type, renderProtoView.transitiveNgContentCount > 0, renderProtoView.render,
|
||||||
protoChangeDetector, variableBindings, createVariableLocations(elementBinders),
|
protoChangeDetector, variableBindings, createVariableLocations(elementBinders),
|
||||||
renderProtoView.textBindings.length);
|
renderProtoView.textBindings.length, protoPipes);
|
||||||
_createElementBinders(protoView, elementBinders, allDirectives);
|
_createElementBinders(protoView, elementBinders, allDirectives);
|
||||||
_bindDirectiveEvents(protoView, elementBinders);
|
_bindDirectiveEvents(protoView, elementBinders);
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ import * as renderApi from 'angular2/src/render/api';
|
|||||||
import {RenderEventDispatcher} from 'angular2/src/render/api';
|
import {RenderEventDispatcher} from 'angular2/src/render/api';
|
||||||
import {ViewRef, ProtoViewRef, internalView} from './view_ref';
|
import {ViewRef, ProtoViewRef, internalView} from './view_ref';
|
||||||
import {ElementRef} from './element_ref';
|
import {ElementRef} from './element_ref';
|
||||||
|
import {ProtoPipes} from 'angular2/src/core/pipes/pipes';
|
||||||
|
|
||||||
export {DebugContext} from 'angular2/src/change_detection/interfaces';
|
export {DebugContext} from 'angular2/src/change_detection/interfaces';
|
||||||
|
|
||||||
@ -335,7 +336,8 @@ export class AppProtoView {
|
|||||||
public render: renderApi.RenderProtoViewRef,
|
public render: renderApi.RenderProtoViewRef,
|
||||||
public protoChangeDetector: ProtoChangeDetector,
|
public protoChangeDetector: ProtoChangeDetector,
|
||||||
public variableBindings: Map<string, string>,
|
public variableBindings: Map<string, string>,
|
||||||
public variableLocations: Map<string, number>, public textBindingCount: number) {
|
public variableLocations: Map<string, number>, public textBindingCount: number,
|
||||||
|
public pipes: ProtoPipes) {
|
||||||
this.ref = new ProtoViewRef(this);
|
this.ref = new ProtoViewRef(this);
|
||||||
if (isPresent(variableBindings)) {
|
if (isPresent(variableBindings)) {
|
||||||
MapWrapper.forEach(variableBindings,
|
MapWrapper.forEach(variableBindings,
|
||||||
|
@ -9,6 +9,7 @@ import {ElementRef} from './element_ref';
|
|||||||
import {TemplateRef} from './template_ref';
|
import {TemplateRef} from './template_ref';
|
||||||
import {Renderer, RenderViewWithFragments} from 'angular2/src/render/api';
|
import {Renderer, RenderViewWithFragments} from 'angular2/src/render/api';
|
||||||
import {Locals} from 'angular2/src/change_detection/change_detection';
|
import {Locals} from 'angular2/src/change_detection/change_detection';
|
||||||
|
import {Pipes} from 'angular2/src/core/pipes/pipes';
|
||||||
import {RenderViewRef, RenderFragmentRef, ViewType} from 'angular2/src/render/api';
|
import {RenderViewRef, RenderFragmentRef, ViewType} from 'angular2/src/render/api';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@ -206,21 +207,15 @@ export class AppViewManagerUtils {
|
|||||||
this._setUpHostActions(currView, elementInjector, boundElementIndex);
|
this._setUpHostActions(currView, elementInjector, boundElementIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var pipes = this._getPipes(imperativelyCreatedInjector, hostElementInjector);
|
var pipes = isPresent(hostElementInjector) ?
|
||||||
|
new Pipes(currView.proto.pipes, hostElementInjector.getInjector()) :
|
||||||
|
null;
|
||||||
currView.changeDetector.hydrate(currView.context, currView.locals, currView, pipes);
|
currView.changeDetector.hydrate(currView.context, currView.locals, currView, pipes);
|
||||||
viewIdx++;
|
viewIdx++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_getPipes(imperativelyCreatedInjector: Injector, hostElementInjector: eli.ElementInjector) {
|
|
||||||
var pipesKey = eli.StaticKeys.instance().pipesKey;
|
|
||||||
if (isPresent(imperativelyCreatedInjector))
|
|
||||||
return imperativelyCreatedInjector.getOptional(pipesKey);
|
|
||||||
if (isPresent(hostElementInjector)) return hostElementInjector.getPipes();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
_populateViewLocals(view: viewModule.AppView, elementInjector: eli.ElementInjector,
|
_populateViewLocals(view: viewModule.AppView, elementInjector: eli.ElementInjector,
|
||||||
boundElementIdx: number): void {
|
boundElementIdx: number): void {
|
||||||
if (isPresent(elementInjector.getDirectiveVariableBindings())) {
|
if (isPresent(elementInjector.getDirectiveVariableBindings())) {
|
||||||
|
15
modules/angular2/src/core/pipes/pipe_binding.ts
Normal file
15
modules/angular2/src/core/pipes/pipe_binding.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import {Type} from 'angular2/src/facade/lang';
|
||||||
|
import {Key, Dependency, ResolvedBinding, Binding} from 'angular2/di';
|
||||||
|
import {Pipe} from 'angular2/src/core/annotations_impl/annotations';
|
||||||
|
|
||||||
|
export class PipeBinding extends ResolvedBinding {
|
||||||
|
constructor(public name: string, key: Key, factory: Function, dependencies: Dependency[]) {
|
||||||
|
super(key, factory, dependencies);
|
||||||
|
}
|
||||||
|
|
||||||
|
static createFromType(type: Type, metadata: Pipe): PipeBinding {
|
||||||
|
var binding = new Binding(type, {toClass: type});
|
||||||
|
var rb = binding.resolve();
|
||||||
|
return new PipeBinding(metadata.name, rb.key, rb.factory, rb.dependencies);
|
||||||
|
}
|
||||||
|
}
|
28
modules/angular2/src/core/pipes/pipes.ts
Normal file
28
modules/angular2/src/core/pipes/pipes.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import {isBlank, isPresent, BaseException, CONST, Type} from 'angular2/src/facade/lang';
|
||||||
|
import {Injectable, OptionalMetadata, SkipSelfMetadata, Binding, Injector, bind} from 'angular2/di';
|
||||||
|
import {PipeBinding} from './pipe_binding';
|
||||||
|
import * as cd from 'angular2/src/change_detection/pipes';
|
||||||
|
|
||||||
|
export class ProtoPipes {
|
||||||
|
/**
|
||||||
|
* Map of {@link Pipe} names to {@link Pipe} implementations.
|
||||||
|
*/
|
||||||
|
config: StringMap<string, PipeBinding> = {};
|
||||||
|
|
||||||
|
constructor(bindings: PipeBinding[]) { bindings.forEach(b => this.config[b.name] = b); }
|
||||||
|
|
||||||
|
get(name: string): PipeBinding {
|
||||||
|
var binding = this.config[name];
|
||||||
|
if (isBlank(binding)) throw new BaseException(`Cannot find pipe '${name}'.`);
|
||||||
|
return binding;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Pipes implements cd.Pipes {
|
||||||
|
constructor(public proto: ProtoPipes, public injector: Injector) {}
|
||||||
|
|
||||||
|
get(name: string): any {
|
||||||
|
var b = this.proto.get(name);
|
||||||
|
return this.injector.instantiateResolved(b);
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,12 @@
|
|||||||
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 {Injectable} from 'angular2/di';
|
import {Injectable} from 'angular2/di';
|
||||||
import {Pipe, WrappedValue, InvalidPipeArgumentException} from './pipe';
|
|
||||||
import {ChangeDetectorRef} from '../change_detector_ref';
|
import {PipeTransform, WrappedValue} from 'angular2/change_detection';
|
||||||
|
import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
|
||||||
|
import {ChangeDetectorRef} from 'angular2/change_detection';
|
||||||
|
|
||||||
|
import {Pipe} from 'angular2/src/core/annotations/decorators';
|
||||||
|
|
||||||
|
|
||||||
class ObservableStrategy {
|
class ObservableStrategy {
|
||||||
@ -53,8 +57,9 @@ var _observableStrategy = new ObservableStrategy();
|
|||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
|
@Pipe({name: 'async'})
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AsyncPipe implements Pipe {
|
export class AsyncPipe implements PipeTransform {
|
||||||
_latestValue: Object = null;
|
_latestValue: Object = null;
|
||||||
_latestReturnedValue: Object = null;
|
_latestReturnedValue: Object = null;
|
||||||
|
|
@ -11,7 +11,11 @@ import {
|
|||||||
import {DateFormatter} from 'angular2/src/facade/intl';
|
import {DateFormatter} from 'angular2/src/facade/intl';
|
||||||
import {Injectable} from 'angular2/di';
|
import {Injectable} from 'angular2/di';
|
||||||
import {StringMapWrapper, ListWrapper} from 'angular2/src/facade/collection';
|
import {StringMapWrapper, ListWrapper} from 'angular2/src/facade/collection';
|
||||||
import {Pipe, BasePipe, InvalidPipeArgumentException} from './pipe';
|
|
||||||
|
import {PipeTransform, WrappedValue, BasePipeTransform} from 'angular2/change_detection';
|
||||||
|
import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
|
||||||
|
|
||||||
|
import {Pipe} from 'angular2/src/core/annotations/decorators';
|
||||||
|
|
||||||
// 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';
|
||||||
@ -71,8 +75,9 @@ var defaultLocale: string = 'en-US';
|
|||||||
* {{ dateObj | date:'mmss' }} // output is '43:11'
|
* {{ dateObj | date:'mmss' }} // output is '43:11'
|
||||||
*/
|
*/
|
||||||
@CONST()
|
@CONST()
|
||||||
|
@Pipe({name: 'date'})
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DatePipe extends BasePipe {
|
export class DatePipe extends BasePipeTransform {
|
||||||
static _ALIASES = {
|
static _ALIASES = {
|
||||||
'medium': 'yMMMdjms',
|
'medium': 'yMMMdjms',
|
||||||
'short': 'yMdjm',
|
'short': 'yMdjm',
|
||||||
@ -102,5 +107,5 @@ export class DatePipe extends BasePipe {
|
|||||||
return DateFormatter.format(value, defaultLocale, pattern);
|
return DateFormatter.format(value, defaultLocale, pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
supports(obj: any): boolean { return isDate(obj) || isNumber(obj); }
|
private supports(obj: any): boolean { return isDate(obj) || isNumber(obj); }
|
||||||
}
|
}
|
27
modules/angular2/src/pipes/default_pipes.ts
Normal file
27
modules/angular2/src/pipes/default_pipes.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import {AsyncPipe} from './async_pipe';
|
||||||
|
import {UpperCasePipe} from './uppercase_pipe';
|
||||||
|
import {LowerCasePipe} from './lowercase_pipe';
|
||||||
|
import {JsonPipe} from './json_pipe';
|
||||||
|
import {LimitToPipe} from './limit_to_pipe';
|
||||||
|
import {DatePipe} from './date_pipe';
|
||||||
|
import {DecimalPipe, PercentPipe, CurrencyPipe} from './number_pipe';
|
||||||
|
|
||||||
|
import {CONST_EXPR} from 'angular2/src/facade/lang';
|
||||||
|
import {Binding, OpaqueToken} from 'angular2/di';
|
||||||
|
|
||||||
|
const DEFAULT_PIPES_LIST = CONST_EXPR([
|
||||||
|
AsyncPipe,
|
||||||
|
UpperCasePipe,
|
||||||
|
LowerCasePipe,
|
||||||
|
JsonPipe,
|
||||||
|
LimitToPipe,
|
||||||
|
DecimalPipe,
|
||||||
|
PercentPipe,
|
||||||
|
CurrencyPipe,
|
||||||
|
DatePipe
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const DEFAULT_PIPES_TOKEN = CONST_EXPR(new OpaqueToken("Default Pipes"));
|
||||||
|
|
||||||
|
export const DEFAULT_PIPES =
|
||||||
|
CONST_EXPR(new Binding(DEFAULT_PIPES_TOKEN, {toValue: DEFAULT_PIPES_LIST}));
|
@ -0,0 +1,7 @@
|
|||||||
|
import {ABSTRACT, BaseException, CONST, Type} from 'angular2/src/facade/lang';
|
||||||
|
|
||||||
|
export class InvalidPipeArgumentException extends BaseException {
|
||||||
|
constructor(type: Type, value: Object) {
|
||||||
|
super(`Invalid argument '${value}' for pipe '${type}'`);
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,9 @@
|
|||||||
import {isBlank, isPresent, Json, CONST} from 'angular2/src/facade/lang';
|
import {isBlank, isPresent, Json, CONST} from 'angular2/src/facade/lang';
|
||||||
import {Injectable} from 'angular2/di';
|
import {Injectable} from 'angular2/di';
|
||||||
import {Pipe, BasePipe} from './pipe';
|
|
||||||
|
import {PipeTransform, WrappedValue, BasePipeTransform} from 'angular2/change_detection';
|
||||||
|
|
||||||
|
import {Pipe} from 'angular2/src/core/annotations/decorators';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements json transforms to any object.
|
* Implements json transforms to any object.
|
||||||
@ -26,7 +29,8 @@ import {Pipe, BasePipe} from './pipe';
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
@CONST()
|
@CONST()
|
||||||
|
@Pipe({name: 'json'})
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class JsonPipe extends BasePipe {
|
export class JsonPipe extends BasePipeTransform {
|
||||||
transform(value: any, args: List<any> = null): string { return Json.stringify(value); }
|
transform(value: any, args: List<any> = null): string { return Json.stringify(value); }
|
||||||
}
|
}
|
@ -9,7 +9,11 @@ import {
|
|||||||
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 {Injectable} from 'angular2/di';
|
import {Injectable} from 'angular2/di';
|
||||||
import {WrappedValue, Pipe, InvalidPipeArgumentException} from './pipe';
|
|
||||||
|
import {PipeTransform, WrappedValue, BasePipeTransform} from 'angular2/change_detection';
|
||||||
|
import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
|
||||||
|
|
||||||
|
import {Pipe} from 'angular2/src/core/annotations/decorators';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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,8 +54,9 @@ import {WrappedValue, Pipe, InvalidPipeArgumentException} from './pipe';
|
|||||||
* {{ 'abcdefghij' | limitTo: -4 }} // output is 'ghij'
|
* {{ 'abcdefghij' | limitTo: -4 }} // output is 'ghij'
|
||||||
* {{ 'abcdefghij' | limitTo: -100 }} // output is 'abcdefghij'
|
* {{ 'abcdefghij' | limitTo: -100 }} // output is 'abcdefghij'
|
||||||
*/
|
*/
|
||||||
|
@Pipe({name: 'limitTo'})
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class LimitToPipe implements Pipe {
|
export class LimitToPipe implements PipeTransform {
|
||||||
supports(obj: any): boolean { return isString(obj) || isArray(obj); }
|
supports(obj: any): boolean { return isString(obj) || isArray(obj); }
|
||||||
|
|
||||||
transform(value: any, args: List<any> = null): any {
|
transform(value: any, args: List<any> = null): any {
|
@ -1,6 +1,11 @@
|
|||||||
import {isString, StringWrapper, CONST, isBlank} from 'angular2/src/facade/lang';
|
import {isString, StringWrapper, CONST, isBlank} from 'angular2/src/facade/lang';
|
||||||
import {Injectable} from 'angular2/di';
|
import {Injectable} from 'angular2/di';
|
||||||
import {Pipe, BasePipe, InvalidPipeArgumentException} from './pipe';
|
|
||||||
|
import {PipeTransform, WrappedValue, BasePipeTransform} from 'angular2/change_detection';
|
||||||
|
import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
|
||||||
|
|
||||||
|
|
||||||
|
import {Pipe} from 'angular2/src/core/annotations/decorators';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements lowercase transforms to text.
|
* Implements lowercase transforms to text.
|
||||||
@ -23,8 +28,9 @@ import {Pipe, BasePipe, InvalidPipeArgumentException} from './pipe';
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
@CONST()
|
@CONST()
|
||||||
|
@Pipe({name: 'lowercase'})
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class LowerCasePipe extends BasePipe {
|
export class LowerCasePipe extends BasePipeTransform {
|
||||||
transform(value: string, args: List<any> = null): string {
|
transform(value: string, args: List<any> = null): string {
|
||||||
if (isBlank(value)) return value;
|
if (isBlank(value)) return value;
|
||||||
if (!isString(value)) {
|
if (!isString(value)) {
|
@ -12,14 +12,18 @@ import {
|
|||||||
import {NumberFormatter, NumberFormatStyle} from 'angular2/src/facade/intl';
|
import {NumberFormatter, NumberFormatStyle} from 'angular2/src/facade/intl';
|
||||||
import {Injectable} from 'angular2/di';
|
import {Injectable} from 'angular2/di';
|
||||||
import {ListWrapper} from 'angular2/src/facade/collection';
|
import {ListWrapper} from 'angular2/src/facade/collection';
|
||||||
import {Pipe, BasePipe, InvalidPipeArgumentException} from './pipe';
|
|
||||||
|
import {PipeTransform, WrappedValue, BasePipeTransform} from 'angular2/change_detection';
|
||||||
|
import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
|
||||||
|
|
||||||
|
import {Pipe} from 'angular2/src/core/annotations/decorators';
|
||||||
|
|
||||||
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()
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class NumberPipe extends BasePipe {
|
export class NumberPipe extends BasePipeTransform {
|
||||||
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 (isBlank(value)) return null;
|
||||||
@ -78,6 +82,8 @@ export class NumberPipe extends BasePipe {
|
|||||||
* {{ 1 | number: '2.2' }} // output is 01.00
|
* {{ 1 | number: '2.2' }} // output is 01.00
|
||||||
*/
|
*/
|
||||||
@CONST()
|
@CONST()
|
||||||
|
@Pipe({name: 'number'})
|
||||||
|
@Injectable()
|
||||||
export class DecimalPipe extends NumberPipe {
|
export class DecimalPipe extends NumberPipe {
|
||||||
transform(value: any, args: any[]): string {
|
transform(value: any, args: any[]): string {
|
||||||
var digits: string = ListWrapper.first(args);
|
var digits: string = ListWrapper.first(args);
|
||||||
@ -95,6 +101,8 @@ export class DecimalPipe extends NumberPipe {
|
|||||||
* For more information about `digitInfo` see {@link DecimalPipe}
|
* For more information about `digitInfo` see {@link DecimalPipe}
|
||||||
*/
|
*/
|
||||||
@CONST()
|
@CONST()
|
||||||
|
@Pipe({name: 'percent'})
|
||||||
|
@Injectable()
|
||||||
export class PercentPipe extends NumberPipe {
|
export class PercentPipe extends NumberPipe {
|
||||||
transform(value: any, args: any[]): string {
|
transform(value: any, args: any[]): string {
|
||||||
var digits: string = ListWrapper.first(args);
|
var digits: string = ListWrapper.first(args);
|
||||||
@ -116,6 +124,8 @@ export class PercentPipe extends NumberPipe {
|
|||||||
* For more information about `digitInfo` see {@link DecimalPipe}
|
* For more information about `digitInfo` see {@link DecimalPipe}
|
||||||
*/
|
*/
|
||||||
@CONST()
|
@CONST()
|
||||||
|
@Pipe({name: 'currency'})
|
||||||
|
@Injectable()
|
||||||
export class CurrencyPipe extends NumberPipe {
|
export class CurrencyPipe extends NumberPipe {
|
||||||
transform(value: any, args: any[]): string {
|
transform(value: any, args: any[]): string {
|
||||||
var currencyCode: string = isPresent(args) && args.length > 0 ? args[0] : 'USD';
|
var currencyCode: string = isPresent(args) && args.length > 0 ? args[0] : 'USD';
|
@ -1,6 +1,10 @@
|
|||||||
import {isString, StringWrapper, CONST, isBlank} from 'angular2/src/facade/lang';
|
import {isString, StringWrapper, CONST, isBlank} from 'angular2/src/facade/lang';
|
||||||
import {Injectable} from 'angular2/di';
|
import {Injectable} from 'angular2/di';
|
||||||
import {Pipe, BasePipe, InvalidPipeArgumentException} from './pipe';
|
|
||||||
|
import {PipeTransform, WrappedValue, BasePipeTransform} from 'angular2/change_detection';
|
||||||
|
import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
|
||||||
|
|
||||||
|
import {Pipe} from 'angular2/src/core/annotations/decorators';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements uppercase transforms to text.
|
* Implements uppercase transforms to text.
|
||||||
@ -23,8 +27,9 @@ import {Pipe, BasePipe, InvalidPipeArgumentException} from './pipe';
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
@CONST()
|
@CONST()
|
||||||
|
@Pipe({name: 'uppercase'})
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UpperCasePipe extends BasePipe {
|
export class UpperCasePipe extends BasePipeTransform {
|
||||||
transform(value: string, args: List<any> = null): string {
|
transform(value: string, args: List<any> = null): string {
|
||||||
if (isBlank(value)) return value;
|
if (isBlank(value)) return value;
|
||||||
if (!isString(value)) {
|
if (!isString(value)) {
|
@ -14,11 +14,6 @@ class SpyProtoChangeDetector extends SpyObject implements ProtoChangeDetector {
|
|||||||
noSuchMethod(m) => super.noSuchMethod(m);
|
noSuchMethod(m) => super.noSuchMethod(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
@proxy
|
|
||||||
class SpyPipe extends SpyObject implements Pipe {
|
|
||||||
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);
|
||||||
|
@ -7,7 +7,6 @@ import {
|
|||||||
|
|
||||||
import {DependencyProvider} from 'angular2/di';
|
import {DependencyProvider} from 'angular2/di';
|
||||||
|
|
||||||
import {BasePipe} from 'angular2/src/change_detection/pipes/pipe';
|
|
||||||
import {SpyObject, proxy} from './test_lib';
|
import {SpyObject, proxy} from './test_lib';
|
||||||
|
|
||||||
export class SpyChangeDetector extends SpyObject {
|
export class SpyChangeDetector extends SpyObject {
|
||||||
@ -18,10 +17,6 @@ export class SpyProtoChangeDetector extends SpyObject {
|
|||||||
constructor() { super(DynamicChangeDetector); }
|
constructor() { super(DynamicChangeDetector); }
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SpyPipe extends SpyObject {
|
|
||||||
constructor() { super(BasePipe); }
|
|
||||||
}
|
|
||||||
|
|
||||||
export class SpyDependencyProvider extends SpyObject {}
|
export class SpyDependencyProvider extends SpyObject {}
|
||||||
|
|
||||||
export class SpyIterableDifferFactory extends SpyObject {}
|
export class SpyIterableDifferFactory extends SpyObject {}
|
||||||
|
@ -7,17 +7,17 @@ import {
|
|||||||
Lexer,
|
Lexer,
|
||||||
ChangeDetection,
|
ChangeDetection,
|
||||||
DynamicChangeDetection,
|
DynamicChangeDetection,
|
||||||
Pipes,
|
|
||||||
defaultPipes,
|
|
||||||
IterableDiffers,
|
IterableDiffers,
|
||||||
defaultIterableDiffers,
|
defaultIterableDiffers,
|
||||||
KeyValueDiffers,
|
KeyValueDiffers,
|
||||||
defaultKeyValueDiffers
|
defaultKeyValueDiffers
|
||||||
} from 'angular2/src/change_detection/change_detection';
|
} from 'angular2/src/change_detection/change_detection';
|
||||||
|
import {DEFAULT_PIPES} from 'angular2/pipes';
|
||||||
import {ExceptionHandler} from 'angular2/src/core/exception_handler';
|
import {ExceptionHandler} from 'angular2/src/core/exception_handler';
|
||||||
import {ViewLoader} from 'angular2/src/render/dom/compiler/view_loader';
|
import {ViewLoader} from 'angular2/src/render/dom/compiler/view_loader';
|
||||||
import {ViewResolver} from 'angular2/src/core/compiler/view_resolver';
|
import {ViewResolver} from 'angular2/src/core/compiler/view_resolver';
|
||||||
import {DirectiveResolver} from 'angular2/src/core/compiler/directive_resolver';
|
import {DirectiveResolver} from 'angular2/src/core/compiler/directive_resolver';
|
||||||
|
import {PipeResolver} from 'angular2/src/core/compiler/pipe_resolver';
|
||||||
import {DynamicComponentLoader} from 'angular2/src/core/compiler/dynamic_component_loader';
|
import {DynamicComponentLoader} from 'angular2/src/core/compiler/dynamic_component_loader';
|
||||||
import {XHR} from 'angular2/src/render/xhr';
|
import {XHR} from 'angular2/src/render/xhr';
|
||||||
import {ComponentUrlMapper} from 'angular2/src/core/compiler/component_url_mapper';
|
import {ComponentUrlMapper} from 'angular2/src/core/compiler/component_url_mapper';
|
||||||
@ -122,7 +122,7 @@ function _getAppBindings() {
|
|||||||
Compiler,
|
Compiler,
|
||||||
CompilerCache,
|
CompilerCache,
|
||||||
bind(ViewResolver).toClass(MockViewResolver),
|
bind(ViewResolver).toClass(MockViewResolver),
|
||||||
defaultPipes,
|
DEFAULT_PIPES,
|
||||||
bind(IterableDiffers).toValue(defaultIterableDiffers),
|
bind(IterableDiffers).toValue(defaultIterableDiffers),
|
||||||
bind(KeyValueDiffers).toValue(defaultKeyValueDiffers),
|
bind(KeyValueDiffers).toValue(defaultKeyValueDiffers),
|
||||||
bind(ChangeDetection).toClass(DynamicChangeDetection),
|
bind(ChangeDetection).toClass(DynamicChangeDetection),
|
||||||
@ -130,6 +130,7 @@ function _getAppBindings() {
|
|||||||
ViewLoader,
|
ViewLoader,
|
||||||
DynamicComponentLoader,
|
DynamicComponentLoader,
|
||||||
DirectiveResolver,
|
DirectiveResolver,
|
||||||
|
PipeResolver,
|
||||||
Parser,
|
Parser,
|
||||||
Lexer,
|
Lexer,
|
||||||
bind(ExceptionHandler).toValue(new ExceptionHandler(DOM)),
|
bind(ExceptionHandler).toValue(new ExceptionHandler(DOM)),
|
||||||
|
@ -269,12 +269,11 @@ class _CodegenState {
|
|||||||
var newValue = _names.getLocalName(r.selfIndex);
|
var newValue = _names.getLocalName(r.selfIndex);
|
||||||
|
|
||||||
var pipe = _names.getPipeName(r.selfIndex);
|
var pipe = _names.getPipeName(r.selfIndex);
|
||||||
var cdRef = 'this.ref';
|
|
||||||
var pipeType = r.name;
|
var pipeType = r.name;
|
||||||
|
|
||||||
var read = '''
|
var read = '''
|
||||||
if ($_IDENTICAL_CHECK_FN($pipe, $_UTIL.uninitialized)) {
|
if ($_IDENTICAL_CHECK_FN($pipe, $_UTIL.uninitialized)) {
|
||||||
$pipe = ${_names.getPipesAccessorName()}.get('$pipeType', $cdRef);
|
$pipe = ${_names.getPipesAccessorName()}.get('$pipeType');
|
||||||
}
|
}
|
||||||
$newValue = $pipe.transform($context, [$argString]);
|
$newValue = $pipe.transform($context, [$argString]);
|
||||||
''';
|
''';
|
||||||
|
@ -268,6 +268,7 @@ export function makeParamDecorator(annotationCls): any {
|
|||||||
return ParamDecorator;
|
return ParamDecorator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function ParamDecorator(cls, unusedKey, index): any {
|
function ParamDecorator(cls, unusedKey, index): any {
|
||||||
var parameters: Array<Array<any>> = Reflect.getMetadata('parameters', cls);
|
var parameters: Array<Array<any>> = Reflect.getMetadata('parameters', cls);
|
||||||
parameters = parameters || [];
|
parameters = parameters || [];
|
||||||
|
@ -10,10 +10,9 @@ import {
|
|||||||
ChangeDetection,
|
ChangeDetection,
|
||||||
DynamicChangeDetection,
|
DynamicChangeDetection,
|
||||||
JitChangeDetection,
|
JitChangeDetection,
|
||||||
PreGeneratedChangeDetection,
|
PreGeneratedChangeDetection
|
||||||
Pipes,
|
|
||||||
defaultPipes
|
|
||||||
} from 'angular2/src/change_detection/change_detection';
|
} from 'angular2/src/change_detection/change_detection';
|
||||||
|
import {DEFAULT_PIPES} from 'angular2/pipes';
|
||||||
import {EventManager, DomEventsPlugin} from 'angular2/src/render/dom/events/event_manager';
|
import {EventManager, DomEventsPlugin} from 'angular2/src/render/dom/events/event_manager';
|
||||||
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
|
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
|
||||||
import {BrowserDomAdapter} from 'angular2/src/dom/browser_adapter';
|
import {BrowserDomAdapter} from 'angular2/src/dom/browser_adapter';
|
||||||
@ -114,7 +113,7 @@ function _injectorBindings(): List<Type | Binding | List<any>> {
|
|||||||
Compiler,
|
Compiler,
|
||||||
CompilerCache,
|
CompilerCache,
|
||||||
ViewResolver,
|
ViewResolver,
|
||||||
bind(Pipes).toValue(defaultPipes),
|
DEFAULT_PIPES,
|
||||||
bind(ChangeDetection).toClass(bestChangeDetection),
|
bind(ChangeDetection).toClass(bestChangeDetection),
|
||||||
ViewLoader,
|
ViewLoader,
|
||||||
DirectiveResolver,
|
DirectiveResolver,
|
||||||
|
@ -18,16 +18,16 @@ import {
|
|||||||
DynamicChangeDetection,
|
DynamicChangeDetection,
|
||||||
JitChangeDetection,
|
JitChangeDetection,
|
||||||
PreGeneratedChangeDetection,
|
PreGeneratedChangeDetection,
|
||||||
Pipes,
|
|
||||||
defaultPipes,
|
|
||||||
IterableDiffers,
|
IterableDiffers,
|
||||||
defaultIterableDiffers,
|
defaultIterableDiffers,
|
||||||
KeyValueDiffers,
|
KeyValueDiffers,
|
||||||
defaultKeyValueDiffers
|
defaultKeyValueDiffers
|
||||||
} from 'angular2/src/change_detection/change_detection';
|
} from 'angular2/src/change_detection/change_detection';
|
||||||
|
import {DEFAULT_PIPES} from 'angular2/pipes';
|
||||||
import {StyleUrlResolver} from 'angular2/src/render/dom/compiler/style_url_resolver';
|
import {StyleUrlResolver} from 'angular2/src/render/dom/compiler/style_url_resolver';
|
||||||
import {ExceptionHandler} from 'angular2/src/core/exception_handler';
|
import {ExceptionHandler} from 'angular2/src/core/exception_handler';
|
||||||
import {DirectiveResolver} from 'angular2/src/core/compiler/directive_resolver';
|
import {DirectiveResolver} from 'angular2/src/core/compiler/directive_resolver';
|
||||||
|
import {PipeResolver} from 'angular2/src/core/compiler/pipe_resolver';
|
||||||
import {ViewResolver} from 'angular2/src/core/compiler/view_resolver';
|
import {ViewResolver} from 'angular2/src/core/compiler/view_resolver';
|
||||||
import {List, ListWrapper} from 'angular2/src/facade/collection';
|
import {List, ListWrapper} from 'angular2/src/facade/collection';
|
||||||
import {Promise, PromiseWrapper, PromiseCompleter} from 'angular2/src/facade/async';
|
import {Promise, PromiseWrapper, PromiseCompleter} from 'angular2/src/facade/async';
|
||||||
@ -123,11 +123,12 @@ function _injectorBindings(appComponentType, bus: WebWorkerMessageBus,
|
|||||||
Compiler,
|
Compiler,
|
||||||
CompilerCache,
|
CompilerCache,
|
||||||
ViewResolver,
|
ViewResolver,
|
||||||
defaultPipes,
|
DEFAULT_PIPES,
|
||||||
bind(IterableDiffers).toValue(defaultIterableDiffers),
|
bind(IterableDiffers).toValue(defaultIterableDiffers),
|
||||||
bind(KeyValueDiffers).toValue(defaultKeyValueDiffers),
|
bind(KeyValueDiffers).toValue(defaultKeyValueDiffers),
|
||||||
bind(ChangeDetection).toClass(bestChangeDetection),
|
bind(ChangeDetection).toClass(bestChangeDetection),
|
||||||
DirectiveResolver,
|
DirectiveResolver,
|
||||||
|
PipeResolver,
|
||||||
Parser,
|
Parser,
|
||||||
Lexer,
|
Lexer,
|
||||||
bind(ExceptionHandler).toFactory(() => new ExceptionHandler(new PrintLogger()), []),
|
bind(ExceptionHandler).toFactory(() => new ExceptionHandler(new PrintLogger()), []),
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
///<reference path="../../src/change_detection/pipes/pipe.ts"/>
|
///<reference path="../../src/change_detection/pipe_transform.ts"/>
|
||||||
import {
|
import {
|
||||||
ddescribe,
|
ddescribe,
|
||||||
describe,
|
describe,
|
||||||
@ -29,8 +29,7 @@ import {
|
|||||||
BindingRecord,
|
BindingRecord,
|
||||||
DirectiveRecord,
|
DirectiveRecord,
|
||||||
DirectiveIndex,
|
DirectiveIndex,
|
||||||
Pipes,
|
PipeTransform,
|
||||||
Pipe,
|
|
||||||
CHECK_ALWAYS,
|
CHECK_ALWAYS,
|
||||||
CHECK_ONCE,
|
CHECK_ONCE,
|
||||||
CHECKED,
|
CHECKED,
|
||||||
@ -45,6 +44,8 @@ import {
|
|||||||
Locals,
|
Locals,
|
||||||
ProtoChangeDetector
|
ProtoChangeDetector
|
||||||
} from 'angular2/src/change_detection/change_detection';
|
} from 'angular2/src/change_detection/change_detection';
|
||||||
|
|
||||||
|
import {Pipes} from 'angular2/src/change_detection/pipes';
|
||||||
import {JitProtoChangeDetector} from 'angular2/src/change_detection/jit_proto_change_detector';
|
import {JitProtoChangeDetector} from 'angular2/src/change_detection/jit_proto_change_detector';
|
||||||
|
|
||||||
import {getDefinition} from './change_detector_config';
|
import {getDefinition} from './change_detector_config';
|
||||||
@ -809,19 +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 inject the ChangeDetectorRef ' +
|
|
||||||
'of the encompassing component into a pipe',
|
|
||||||
() => {
|
|
||||||
|
|
||||||
var registry = new FakePipes('pipe', () => new IdentityPipe());
|
|
||||||
var cd =
|
|
||||||
_createChangeDetector('name | pipe', new Person('bob'), registry).changeDetector;
|
|
||||||
|
|
||||||
cd.detectChanges();
|
|
||||||
|
|
||||||
expect(registry.cdRef).toBe(cd.ref);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should do nothing when no change', () => {
|
it('should do nothing when no change', () => {
|
||||||
@ -854,30 +842,30 @@ export function main() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class CountingPipe implements Pipe {
|
class CountingPipe implements PipeTransform {
|
||||||
state: number = 0;
|
state: number = 0;
|
||||||
onDestroy() {}
|
onDestroy() {}
|
||||||
transform(value, args = null) { return `${value} state:${this.state ++}`; }
|
transform(value, args = null) { return `${value} state:${this.state ++}`; }
|
||||||
}
|
}
|
||||||
|
|
||||||
class PipeWithOnDestroy implements Pipe {
|
class PipeWithOnDestroy implements PipeTransform {
|
||||||
destroyCalled: boolean = false;
|
destroyCalled: boolean = false;
|
||||||
onDestroy() { this.destroyCalled = true; }
|
onDestroy() { this.destroyCalled = true; }
|
||||||
|
|
||||||
transform(value, args = null) { return null; }
|
transform(value, args = null) { return null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
class IdentityPipe implements Pipe {
|
class IdentityPipe implements PipeTransform {
|
||||||
onDestroy() {}
|
onDestroy() {}
|
||||||
transform(value, args = null) { return value; }
|
transform(value, args = null) { return value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
class WrappedPipe implements Pipe {
|
class WrappedPipe implements PipeTransform {
|
||||||
onDestroy() {}
|
onDestroy() {}
|
||||||
transform(value, args = null) { return WrappedValue.wrap(value); }
|
transform(value, args = null) { return WrappedValue.wrap(value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
class MultiArgPipe implements Pipe {
|
class MultiArgPipe implements PipeTransform {
|
||||||
transform(value, args = null) {
|
transform(value, args = null) {
|
||||||
var arg1 = args[0];
|
var arg1 = args[0];
|
||||||
var arg2 = args[1];
|
var arg2 = args[1];
|
||||||
@ -887,16 +875,14 @@ class MultiArgPipe implements Pipe {
|
|||||||
onDestroy(): void {}
|
onDestroy(): void {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FakePipes extends Pipes {
|
class FakePipes implements Pipes {
|
||||||
numberOfLookups = 0;
|
numberOfLookups = 0;
|
||||||
cdRef: any;
|
|
||||||
|
|
||||||
constructor(public pipeType: string, public factory: Function) { super(null, null); }
|
constructor(public pipeType: string, public factory: Function) {}
|
||||||
|
|
||||||
get(type: string, cdRef?) {
|
get(type: string) {
|
||||||
if (type != this.pipeType) return null;
|
if (type != this.pipeType) return null;
|
||||||
this.numberOfLookups++;
|
this.numberOfLookups++;
|
||||||
this.cdRef = cdRef;
|
|
||||||
return this.factory();
|
return this.factory();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,88 +0,0 @@
|
|||||||
import {
|
|
||||||
ddescribe,
|
|
||||||
xdescribe,
|
|
||||||
describe,
|
|
||||||
it,
|
|
||||||
iit,
|
|
||||||
xit,
|
|
||||||
expect,
|
|
||||||
beforeEach,
|
|
||||||
afterEach
|
|
||||||
} from 'angular2/test_lib';
|
|
||||||
|
|
||||||
import {Injector, bind} from 'angular2/di';
|
|
||||||
import {Pipes} from 'angular2/src/change_detection/pipes/pipes';
|
|
||||||
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() {
|
|
||||||
describe("pipe registry", () => {
|
|
||||||
var injector;
|
|
||||||
|
|
||||||
beforeEach(() => { injector = Injector.resolveAndCreate([]); });
|
|
||||||
|
|
||||||
it("should instantiate a pipe", () => {
|
|
||||||
var r = new Pipes({"type": APipe}, injector);
|
|
||||||
expect(r.get("type", null)).toBeAnInstanceOf(APipe);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should instantiate a new pipe every time", () => {
|
|
||||||
var r = new Pipes({"type": APipe}, injector);
|
|
||||||
var p1 = r.get("type", null);
|
|
||||||
var p2 = r.get("type", null);
|
|
||||||
expect(p1).not.toBe(p2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should throw when no matching type", () => {
|
|
||||||
var r = new Pipes({}, null);
|
|
||||||
expect(() => r.get("unknown", null)).toThrowError(`Cannot find pipe 'unknown'.`);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('.create()', () => {
|
|
||||||
it("should create a new Pipes object", () => {
|
|
||||||
var pipes = Pipes.create({'pipe': APipe}, null);
|
|
||||||
expect(pipes.config).toEqual({'pipe': APipe});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should merge pipes config", () => {
|
|
||||||
var pipes1 = Pipes.create({'pipe': APipe, 'pipe1': APipe}, null);
|
|
||||||
var pipes2 = Pipes.create({'pipe': AnotherPipe, 'pipe2': AnotherPipe}, null, pipes1);
|
|
||||||
|
|
||||||
expect(pipes2.config).toEqual({'pipe': AnotherPipe, 'pipe1': APipe, 'pipe2': AnotherPipe});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should not change parent's config", () => {
|
|
||||||
var pipes1 = Pipes.create({'pipe': APipe, 'pipe1': APipe}, null);
|
|
||||||
Pipes.create({'pipe': AnotherPipe, 'pipe2': AnotherPipe}, null, pipes1);
|
|
||||||
|
|
||||||
expect(pipes1.config).toEqual({'pipe': APipe, 'pipe1': APipe});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe(".extend()", () => {
|
|
||||||
it('should create a factory that prepend new pipes to old', () => {
|
|
||||||
var pipes1 = Pipes.create({'pipe': APipe, 'pipe1': APipe}, null);
|
|
||||||
var binding = Pipes.extend({'pipe': AnotherPipe, 'pipe2': AnotherPipe});
|
|
||||||
var pipes: Pipes = binding.toFactory(pipes1, injector);
|
|
||||||
|
|
||||||
expect(pipes.config).toEqual({'pipe': AnotherPipe, 'pipe1': APipe, 'pipe2': AnotherPipe});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw if calling extend when creating root injector', () => {
|
|
||||||
var injector = Injector.resolveAndCreate([Pipes.extend({'pipe': APipe})]);
|
|
||||||
|
|
||||||
expect(() => injector.get(Pipes))
|
|
||||||
.toThrowErrorWith("Cannot extend Pipes without a parent injector");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
@ -22,7 +22,8 @@ import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
|
|||||||
import {AppProtoView} from 'angular2/src/core/compiler/view';
|
import {AppProtoView} from 'angular2/src/core/compiler/view';
|
||||||
import {ElementBinder} from 'angular2/src/core/compiler/element_binder';
|
import {ElementBinder} from 'angular2/src/core/compiler/element_binder';
|
||||||
import {DirectiveResolver} from 'angular2/src/core/compiler/directive_resolver';
|
import {DirectiveResolver} from 'angular2/src/core/compiler/directive_resolver';
|
||||||
import {Attribute, View, Component, Directive} from 'angular2/annotations';
|
import {PipeResolver} from 'angular2/src/core/compiler/pipe_resolver';
|
||||||
|
import {Attribute, View, Component, Directive, Pipe} from 'angular2/annotations';
|
||||||
import * as viewAnn from 'angular2/src/core/annotations_impl/view';
|
import * as viewAnn from 'angular2/src/core/annotations_impl/view';
|
||||||
import {internalProtoView} from 'angular2/src/core/compiler/view_ref';
|
import {internalProtoView} from 'angular2/src/core/compiler/view_ref';
|
||||||
import {DirectiveBinding} from 'angular2/src/core/compiler/element_injector';
|
import {DirectiveBinding} from 'angular2/src/core/compiler/element_injector';
|
||||||
@ -38,11 +39,14 @@ import {AppRootUrl} from 'angular2/src/services/app_root_url';
|
|||||||
import * as renderApi from 'angular2/src/render/api';
|
import * as renderApi from 'angular2/src/render/api';
|
||||||
// TODO(tbosch): Spys don't support named modules...
|
// TODO(tbosch): Spys don't support named modules...
|
||||||
import {RenderCompiler} from 'angular2/src/render/api';
|
import {RenderCompiler} from 'angular2/src/render/api';
|
||||||
|
import {PipeBinding} from 'angular2/src/core/pipes/pipe_binding';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
describe('compiler', function() {
|
describe('compiler', function() {
|
||||||
var directiveResolver, tplResolver, renderCompiler, protoViewFactory, cmpUrlMapper,
|
var directiveResolver, pipeResolver, tplResolver, renderCompiler, protoViewFactory,
|
||||||
rootProtoView;
|
cmpUrlMapper, rootProtoView;
|
||||||
var renderCompileRequests: any[];
|
var renderCompileRequests: any[];
|
||||||
|
|
||||||
function createCompiler(renderCompileResults:
|
function createCompiler(renderCompileResults:
|
||||||
@ -57,13 +61,14 @@ export function main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
protoViewFactory = new FakeProtoViewFactory(protoViewFactoryResults);
|
protoViewFactory = new FakeProtoViewFactory(protoViewFactoryResults);
|
||||||
return new Compiler(directiveResolver, new CompilerCache(), tplResolver, cmpUrlMapper,
|
return new Compiler(directiveResolver, pipeResolver, [SomeDefaultPipe], new CompilerCache(),
|
||||||
urlResolver, renderCompiler, protoViewFactory,
|
tplResolver, cmpUrlMapper, urlResolver, renderCompiler, protoViewFactory,
|
||||||
new AppRootUrl("http://www.app.com"));
|
new AppRootUrl("http://www.app.com"));
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
directiveResolver = new DirectiveResolver();
|
directiveResolver = new DirectiveResolver();
|
||||||
|
pipeResolver = new PipeResolver();
|
||||||
tplResolver = new FakeViewResolver();
|
tplResolver = new FakeViewResolver();
|
||||||
cmpUrlMapper = new RuntimeComponentUrlMapper();
|
cmpUrlMapper = new RuntimeComponentUrlMapper();
|
||||||
renderCompiler = new SpyRenderCompiler();
|
renderCompiler = new SpyRenderCompiler();
|
||||||
@ -304,6 +309,20 @@ export function main() {
|
|||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it('should pass the pipe bindings', inject([AsyncTestCompleter], (async) => {
|
||||||
|
tplResolver.setView(MainComponent,
|
||||||
|
new viewAnn.View({template: '<div></div>', pipes: [SomePipe]}));
|
||||||
|
var compiler =
|
||||||
|
createCompiler([createRenderProtoView()], [rootProtoView, createProtoView()]);
|
||||||
|
compiler.compileInHost(MainComponent)
|
||||||
|
.then((_) => {
|
||||||
|
var request = protoViewFactory.requests[1];
|
||||||
|
expect(request[3][0].key.token).toBe(SomeDefaultPipe);
|
||||||
|
expect(request[3][1].key.token).toBe(SomePipe);
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
it('should use the protoView of the ProtoViewFactory',
|
it('should use the protoView of the ProtoViewFactory',
|
||||||
inject([AsyncTestCompleter], (async) => {
|
inject([AsyncTestCompleter], (async) => {
|
||||||
tplResolver.setView(MainComponent, new viewAnn.View({template: '<div></div>'}));
|
tplResolver.setView(MainComponent, new viewAnn.View({template: '<div></div>'}));
|
||||||
@ -399,9 +418,9 @@ export function main() {
|
|||||||
var reader: any = new SpyDirectiveResolver();
|
var reader: any = new SpyDirectiveResolver();
|
||||||
|
|
||||||
// create the compiler
|
// create the compiler
|
||||||
var compiler =
|
var compiler = new Compiler(reader, pipeResolver, [], cache, tplResolver, cmpUrlMapper,
|
||||||
new Compiler(reader, cache, tplResolver, cmpUrlMapper, new UrlResolver(),
|
new UrlResolver(), renderCompiler, protoViewFactory,
|
||||||
renderCompiler, protoViewFactory, new AppRootUrl("http://www.app.com"));
|
new AppRootUrl("http://www.app.com"));
|
||||||
compiler.compileInHost(MainComponent)
|
compiler.compileInHost(MainComponent)
|
||||||
.then((protoViewRef) => {
|
.then((protoViewRef) => {
|
||||||
// the test should have failed if the resolver was called, so we're good
|
// the test should have failed if the resolver was called, so we're good
|
||||||
@ -570,7 +589,7 @@ function createProtoView(elementBinders = null, type: renderApi.ViewType = null,
|
|||||||
type = renderApi.ViewType.COMPONENT;
|
type = renderApi.ViewType.COMPONENT;
|
||||||
}
|
}
|
||||||
var pv = new AppProtoView(type, isEmbeddedFragment, new renderApi.RenderProtoViewRef(), null,
|
var pv = new AppProtoView(type, isEmbeddedFragment, new renderApi.RenderProtoViewRef(), null,
|
||||||
null, new Map(), null);
|
null, new Map(), null, null);
|
||||||
if (isBlank(elementBinders)) {
|
if (isBlank(elementBinders)) {
|
||||||
elementBinders = [];
|
elementBinders = [];
|
||||||
}
|
}
|
||||||
@ -653,6 +672,14 @@ class DirectiveWithProperties {
|
|||||||
class DirectiveWithBind {
|
class DirectiveWithBind {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Pipe({name: 'some-default-pipe'})
|
||||||
|
class SomeDefaultPipe {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Pipe({name: 'some-pipe'})
|
||||||
|
class SomePipe {
|
||||||
|
}
|
||||||
|
|
||||||
@Directive({selector: 'directive-with-accts'})
|
@Directive({selector: 'directive-with-accts'})
|
||||||
class DirectiveWithAttributes {
|
class DirectiveWithAttributes {
|
||||||
constructor(@Attribute('someAttr') someAttr: String) {}
|
constructor(@Attribute('someAttr') someAttr: String) {}
|
||||||
@ -694,8 +721,8 @@ class FakeProtoViewFactory extends ProtoViewFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createAppProtoViews(componentBinding: DirectiveBinding, renderProtoView: renderApi.ProtoViewDto,
|
createAppProtoViews(componentBinding: DirectiveBinding, renderProtoView: renderApi.ProtoViewDto,
|
||||||
directives: List<DirectiveBinding>): AppProtoView[] {
|
directives: List<DirectiveBinding>, pipes: PipeBinding[]): AppProtoView[] {
|
||||||
this.requests.push([componentBinding, renderProtoView, directives]);
|
this.requests.push([componentBinding, renderProtoView, directives, pipes]);
|
||||||
return collectEmbeddedPvs(ListWrapper.removeAt(this.results, 0));
|
return collectEmbeddedPvs(ListWrapper.removeAt(this.results, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,14 +192,17 @@ class OptionallyInjectsTemplateRef {
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
class DirectiveNeedsChangeDetectorRef {
|
class DirectiveNeedsChangeDetectorRef {
|
||||||
changeDetectorRef;
|
constructor(public changeDetectorRef: ChangeDetectorRef) {}
|
||||||
constructor(cdr: ChangeDetectorRef) { this.changeDetectorRef = cdr; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
class ComponentNeedsChangeDetectorRef {
|
class ComponentNeedsChangeDetectorRef {
|
||||||
changeDetectorRef;
|
constructor(public changeDetectorRef: ChangeDetectorRef) {}
|
||||||
constructor(cdr: ChangeDetectorRef) { this.changeDetectorRef = cdr; }
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
class PipeNeedsChangeDetectorRef {
|
||||||
|
constructor(public changeDetectorRef: ChangeDetectorRef) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class A_Needs_B {
|
class A_Needs_B {
|
||||||
|
@ -55,15 +55,14 @@ import {
|
|||||||
SkipSelf,
|
SkipSelf,
|
||||||
SkipSelfMetadata
|
SkipSelfMetadata
|
||||||
} from 'angular2/di';
|
} from 'angular2/di';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Pipes,
|
PipeTransform,
|
||||||
defaultPipes,
|
|
||||||
Pipe,
|
|
||||||
ChangeDetectorRef,
|
ChangeDetectorRef,
|
||||||
ON_PUSH
|
ON_PUSH
|
||||||
} from 'angular2/src/change_detection/change_detection';
|
} from 'angular2/src/change_detection/change_detection';
|
||||||
|
|
||||||
import {Directive, Component, View, Attribute, Query} from 'angular2/annotations';
|
import {Directive, Component, View, Attribute, Query, Pipe} from 'angular2/annotations';
|
||||||
import * as viewAnn from 'angular2/src/core/annotations_impl/view';
|
import * as viewAnn from 'angular2/src/core/annotations_impl/view';
|
||||||
|
|
||||||
import {QueryList} from 'angular2/src/core/compiler/query_list';
|
import {QueryList} from 'angular2/src/core/compiler/query_list';
|
||||||
@ -98,6 +97,7 @@ export function main() {
|
|||||||
rootTC.detectChanges();
|
rootTC.detectChanges();
|
||||||
expect(rootTC.nativeElement).toHaveText('Hello World!');
|
expect(rootTC.nativeElement).toHaveText('Hello World!');
|
||||||
async.done();
|
async.done();
|
||||||
|
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -242,12 +242,13 @@ export function main() {
|
|||||||
it("should support pipes in bindings",
|
it("should support pipes in bindings",
|
||||||
inject([TestComponentBuilder, AsyncTestCompleter],
|
inject([TestComponentBuilder, AsyncTestCompleter],
|
||||||
(tcb: TestComponentBuilder, async) => {
|
(tcb: TestComponentBuilder, async) => {
|
||||||
tcb.overrideView(MyCompWithPipes, new viewAnn.View({
|
tcb.overrideView(MyComp, new viewAnn.View({
|
||||||
template: '<div my-dir #dir="mydir" [elprop]="ctxProp | double"></div>',
|
template: '<div my-dir #dir="mydir" [elprop]="ctxProp | double"></div>',
|
||||||
directives: [MyDir]
|
directives: [MyDir],
|
||||||
|
pipes: [DoublePipe]
|
||||||
}))
|
}))
|
||||||
|
|
||||||
.createAsync(MyCompWithPipes)
|
.createAsync(MyComp)
|
||||||
.then((rootTC) => {
|
.then((rootTC) => {
|
||||||
rootTC.componentInstance.ctxProp = 'a';
|
rootTC.componentInstance.ctxProp = 'a';
|
||||||
rootTC.detectChanges();
|
rootTC.detectChanges();
|
||||||
@ -1661,21 +1662,6 @@ class PushCmpWithAsyncPipe {
|
|||||||
resolve(value) { this.completer.resolve(value); }
|
resolve(value) { this.completer.resolve(value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
class PipesWithDouble extends Pipes {
|
|
||||||
constructor(injector: Injector) { super({"double": DoublePipe}, injector); }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'my-comp-with-pipes',
|
|
||||||
viewBindings: [new Binding(Pipes, {toClass: PipesWithDouble})]
|
|
||||||
})
|
|
||||||
@View({directives: []})
|
|
||||||
@Injectable()
|
|
||||||
class MyCompWithPipes {
|
|
||||||
ctxProp: string = "initial value";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({selector: 'my-comp'})
|
@Component({selector: 'my-comp'})
|
||||||
@View({directives: []})
|
@View({directives: []})
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@ -1754,8 +1740,8 @@ class SomeViewport {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Pipe({name: 'double'})
|
||||||
class DoublePipe implements Pipe {
|
class DoublePipe implements PipeTransform {
|
||||||
onDestroy() {}
|
onDestroy() {}
|
||||||
transform(value, args = null) { return `${value}${value}`; }
|
transform(value, args = null) { return `${value}${value}`; }
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ export function main() {
|
|||||||
varBindings.set('a', 'b');
|
varBindings.set('a', 'b');
|
||||||
var renderPv = createRenderProtoView([], null, varBindings);
|
var renderPv = createRenderProtoView([], null, varBindings);
|
||||||
var appPvs =
|
var appPvs =
|
||||||
protoViewFactory.createAppProtoViews(bindDirective(MainComponent), renderPv, []);
|
protoViewFactory.createAppProtoViews(bindDirective(MainComponent), renderPv, [], []);
|
||||||
expect(appPvs[0].variableBindings.get('a')).toEqual('b');
|
expect(appPvs[0].variableBindings.get('a')).toEqual('b');
|
||||||
expect(appPvs.length).toBe(1);
|
expect(appPvs.length).toBe(1);
|
||||||
});
|
});
|
||||||
|
@ -318,7 +318,7 @@ function _createProtoView(type: ViewType, binders: ElementBinder[] = null) {
|
|||||||
}
|
}
|
||||||
var protoChangeDetector = <any>new SpyProtoChangeDetector();
|
var protoChangeDetector = <any>new SpyProtoChangeDetector();
|
||||||
protoChangeDetector.spy('instantiate').andReturn(new SpyChangeDetector());
|
protoChangeDetector.spy('instantiate').andReturn(new SpyChangeDetector());
|
||||||
var res = new AppProtoView(type, null, null, protoChangeDetector, null, null, 0);
|
var res = new AppProtoView(type, null, null, protoChangeDetector, null, null, 0, null);
|
||||||
res.elementBinders = binders;
|
res.elementBinders = binders;
|
||||||
var mappedElementIndices = ListWrapper.createFixedSize(countNestedElementBinders(res));
|
var mappedElementIndices = ListWrapper.createFixedSize(countNestedElementBinders(res));
|
||||||
for (var i = 0; i < binders.length; i++) {
|
for (var i = 0; i < binders.length; i++) {
|
||||||
|
@ -25,7 +25,7 @@ export function main() {
|
|||||||
function createViewPool({capacity}): AppViewPool { return new AppViewPool(capacity); }
|
function createViewPool({capacity}): AppViewPool { return new AppViewPool(capacity); }
|
||||||
|
|
||||||
function createProtoView() {
|
function createProtoView() {
|
||||||
return new AppProtoView(null, null, null, null, null, null, null);
|
return new AppProtoView(null, null, null, null, null, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
function createView(pv) {
|
function createView(pv) {
|
||||||
|
27
modules/angular2/test/core/pipes/pipe_binding_spec.ts
Normal file
27
modules/angular2/test/core/pipes/pipe_binding_spec.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import {
|
||||||
|
ddescribe,
|
||||||
|
xdescribe,
|
||||||
|
describe,
|
||||||
|
it,
|
||||||
|
iit,
|
||||||
|
xit,
|
||||||
|
expect,
|
||||||
|
beforeEach,
|
||||||
|
afterEach
|
||||||
|
} from 'angular2/test_lib';
|
||||||
|
|
||||||
|
import {PipeBinding} from 'angular2/src/core/pipes/pipe_binding';
|
||||||
|
import {Pipe} from 'angular2/src/core/annotations_impl/annotations';
|
||||||
|
|
||||||
|
class MyPipe {}
|
||||||
|
|
||||||
|
export function main() {
|
||||||
|
describe("PipeBinding", () => {
|
||||||
|
it('should create a binding out of a type', () => {
|
||||||
|
var binding = PipeBinding.createFromType(MyPipe, new Pipe({name: 'my-pipe'}));
|
||||||
|
expect(binding.name).toEqual('my-pipe');
|
||||||
|
expect(binding.factory()).toBeAnInstanceOf(MyPipe);
|
||||||
|
expect(binding.dependencies.length).toEqual(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
56
modules/angular2/test/core/pipes/pipes_spec.ts
Normal file
56
modules/angular2/test/core/pipes/pipes_spec.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import {
|
||||||
|
ddescribe,
|
||||||
|
xdescribe,
|
||||||
|
describe,
|
||||||
|
it,
|
||||||
|
iit,
|
||||||
|
xit,
|
||||||
|
expect,
|
||||||
|
beforeEach,
|
||||||
|
afterEach
|
||||||
|
} from 'angular2/test_lib';
|
||||||
|
|
||||||
|
import {PipeTransform} from 'angular2/change_detection';
|
||||||
|
import {Injector, Inject, bind} from 'angular2/di';
|
||||||
|
import {ProtoPipes, Pipes} from 'angular2/src/core/pipes/pipes';
|
||||||
|
import {PipeBinding} from 'angular2/src/core/pipes/pipe_binding';
|
||||||
|
import {Pipe} from 'angular2/src/core/annotations_impl/annotations';
|
||||||
|
|
||||||
|
class PipeA implements PipeTransform {
|
||||||
|
transform(a, b) {}
|
||||||
|
onDestroy() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PipeB implements PipeTransform {
|
||||||
|
dep;
|
||||||
|
constructor(@Inject("dep") dep: any) { this.dep = dep; }
|
||||||
|
transform(a, b) {}
|
||||||
|
onDestroy() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function main() {
|
||||||
|
describe("Pipes", () => {
|
||||||
|
var injector;
|
||||||
|
|
||||||
|
beforeEach(
|
||||||
|
() => { injector = Injector.resolveAndCreate([bind('dep').toValue('dependency')]); });
|
||||||
|
|
||||||
|
it('should instantiate a pipe', () => {
|
||||||
|
var proto = new ProtoPipes([PipeBinding.createFromType(PipeA, new Pipe({name: 'a'}))]);
|
||||||
|
var pipes = new Pipes(proto, injector);
|
||||||
|
expect(pipes.get("a")).toBeAnInstanceOf(PipeA);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw when no pipe found', () => {
|
||||||
|
var proto = new ProtoPipes([]);
|
||||||
|
var pipes = new Pipes(proto, injector);
|
||||||
|
expect(() => pipes.get("invalid")).toThrowErrorWith("Cannot find pipe 'invalid'");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should inject dependencies from the provided injector', () => {
|
||||||
|
var proto = new ProtoPipes([PipeBinding.createFromType(PipeB, new Pipe({name: 'b'}))]);
|
||||||
|
var pipes = new Pipes(proto, injector);
|
||||||
|
expect(pipes.get("b").dep).toEqual("dependency");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
@ -14,8 +14,8 @@ import {
|
|||||||
} from 'angular2/test_lib';
|
} from 'angular2/test_lib';
|
||||||
|
|
||||||
import {IMPLEMENTS, isBlank} from 'angular2/src/facade/lang';
|
import {IMPLEMENTS, isBlank} from 'angular2/src/facade/lang';
|
||||||
import {WrappedValue} from 'angular2/src/change_detection/pipes/pipe';
|
import {WrappedValue} from 'angular2/change_detection';
|
||||||
import {AsyncPipe} from 'angular2/src/change_detection/pipes/async_pipe';
|
import {AsyncPipe} from 'angular2/pipes';
|
||||||
import {
|
import {
|
||||||
EventEmitter,
|
EventEmitter,
|
||||||
ObservableWrapper,
|
ObservableWrapper,
|
@ -1,6 +1,6 @@
|
|||||||
import {ddescribe, describe, it, iit, xit, expect, beforeEach, afterEach} from 'angular2/test_lib';
|
import {ddescribe, describe, it, iit, xit, expect, beforeEach, afterEach} from 'angular2/test_lib';
|
||||||
|
|
||||||
import {DatePipe} from 'angular2/src/change_detection/pipes/date_pipe';
|
import {DatePipe} from 'angular2/pipes';
|
||||||
import {DateWrapper} from 'angular2/src/facade/lang';
|
import {DateWrapper} from 'angular2/src/facade/lang';
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
@ -15,7 +15,7 @@ import {
|
|||||||
} from 'angular2/test_lib';
|
} from 'angular2/test_lib';
|
||||||
import {Json, RegExp, NumberWrapper, StringWrapper} from 'angular2/src/facade/lang';
|
import {Json, RegExp, NumberWrapper, StringWrapper} from 'angular2/src/facade/lang';
|
||||||
|
|
||||||
import {JsonPipe} from 'angular2/src/change_detection/pipes/json_pipe';
|
import {JsonPipe} from 'angular2/pipes';
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
describe("JsonPipe", () => {
|
describe("JsonPipe", () => {
|
@ -1,6 +1,6 @@
|
|||||||
import {ddescribe, describe, it, iit, xit, expect, beforeEach, afterEach} from 'angular2/test_lib';
|
import {ddescribe, describe, it, iit, xit, expect, beforeEach, afterEach} from 'angular2/test_lib';
|
||||||
|
|
||||||
import {LimitToPipe} from 'angular2/src/change_detection/pipes/limit_to_pipe';
|
import {LimitToPipe} from 'angular2/pipes';
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
describe("LimitToPipe", () => {
|
describe("LimitToPipe", () => {
|
@ -1,6 +1,6 @@
|
|||||||
import {ddescribe, describe, it, iit, xit, expect, beforeEach, afterEach} from 'angular2/test_lib';
|
import {ddescribe, describe, it, iit, xit, expect, beforeEach, afterEach} from 'angular2/test_lib';
|
||||||
|
|
||||||
import {LowerCasePipe} from 'angular2/src/change_detection/pipes/lowercase_pipe';
|
import {LowerCasePipe} from 'angular2/pipes';
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
describe("LowerCasePipe", () => {
|
describe("LowerCasePipe", () => {
|
@ -1,10 +1,6 @@
|
|||||||
import {ddescribe, describe, it, iit, xit, expect, beforeEach, afterEach} from 'angular2/test_lib';
|
import {ddescribe, describe, it, iit, xit, expect, beforeEach, afterEach} from 'angular2/test_lib';
|
||||||
|
|
||||||
import {
|
import {DecimalPipe, PercentPipe, CurrencyPipe} from 'angular2/pipes';
|
||||||
DecimalPipe,
|
|
||||||
PercentPipe,
|
|
||||||
CurrencyPipe
|
|
||||||
} from 'angular2/src/change_detection/pipes/number_pipe';
|
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
describe("DecimalPipe", () => {
|
describe("DecimalPipe", () => {
|
||||||
@ -18,6 +14,7 @@ export function main() {
|
|||||||
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');
|
||||||
expect(pipe.transform(1.1, ['3.4-5'])).toEqual('001.1000');
|
expect(pipe.transform(1.1, ['3.4-5'])).toEqual('001.1000');
|
||||||
|
|
||||||
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');
|
||||||
});
|
});
|
@ -1,6 +1,6 @@
|
|||||||
import {ddescribe, describe, it, iit, xit, expect, beforeEach, afterEach} from 'angular2/test_lib';
|
import {ddescribe, describe, it, iit, xit, expect, beforeEach, afterEach} from 'angular2/test_lib';
|
||||||
|
|
||||||
import {UpperCasePipe} from 'angular2/src/change_detection/pipes/uppercase_pipe';
|
import {UpperCasePipe} from 'angular2/pipes';
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
describe("UpperCasePipe", () => {
|
describe("UpperCasePipe", () => {
|
@ -26,9 +26,17 @@ import {
|
|||||||
routerDirectives
|
routerDirectives
|
||||||
} from 'angular2/router';
|
} from 'angular2/router';
|
||||||
|
|
||||||
|
import {ExceptionHandler} from 'angular2/src/core/exception_handler';
|
||||||
import {LocationStrategy} from 'angular2/src/router/location_strategy';
|
import {LocationStrategy} from 'angular2/src/router/location_strategy';
|
||||||
import {MockLocationStrategy} from 'angular2/src/mock/mock_location_strategy';
|
import {MockLocationStrategy} from 'angular2/src/mock/mock_location_strategy';
|
||||||
|
|
||||||
|
class _ArrayLogger {
|
||||||
|
res: any[] = [];
|
||||||
|
log(s: any): void { this.res.push(s); }
|
||||||
|
logGroup(s: any): void { this.res.push(s); }
|
||||||
|
logGroupEnd(){};
|
||||||
|
}
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
describe('RouteConfig with POJO arguments', () => {
|
describe('RouteConfig with POJO arguments', () => {
|
||||||
var fakeDoc, el, testBindings;
|
var fakeDoc, el, testBindings;
|
||||||
@ -36,10 +44,13 @@ export function main() {
|
|||||||
fakeDoc = DOM.createHtmlDocument();
|
fakeDoc = DOM.createHtmlDocument();
|
||||||
el = DOM.createElement('app-cmp', fakeDoc);
|
el = DOM.createElement('app-cmp', fakeDoc);
|
||||||
DOM.appendChild(fakeDoc.body, el);
|
DOM.appendChild(fakeDoc.body, el);
|
||||||
|
var logger = new _ArrayLogger();
|
||||||
|
var exceptionHandler = new ExceptionHandler(logger, true);
|
||||||
testBindings = [
|
testBindings = [
|
||||||
routerInjectables,
|
routerInjectables,
|
||||||
bind(LocationStrategy).toClass(MockLocationStrategy),
|
bind(LocationStrategy).toClass(MockLocationStrategy),
|
||||||
bind(DOCUMENT_TOKEN).toValue(fakeDoc)
|
bind(DOCUMENT_TOKEN).toValue(fakeDoc),
|
||||||
|
bind(ExceptionHandler).toValue(exceptionHandler)
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ import {
|
|||||||
|
|
||||||
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
|
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
|
||||||
import {DirectiveResolver} from 'angular2/src/core/compiler/directive_resolver';
|
import {DirectiveResolver} from 'angular2/src/core/compiler/directive_resolver';
|
||||||
|
import {PipeResolver} from 'angular2/src/core/compiler/pipe_resolver';
|
||||||
|
|
||||||
import * as viewModule from 'angular2/src/core/annotations_impl/view';
|
import * as viewModule from 'angular2/src/core/annotations_impl/view';
|
||||||
import {Component, Directive, View} from 'angular2/angular2';
|
import {Component, Directive, View} from 'angular2/angular2';
|
||||||
@ -38,6 +39,7 @@ export function main() {
|
|||||||
|
|
||||||
reflector.reflectionCapabilities = new ReflectionCapabilities();
|
reflector.reflectionCapabilities = new ReflectionCapabilities();
|
||||||
var reader = new DirectiveResolver();
|
var reader = new DirectiveResolver();
|
||||||
|
var pipeResolver = new PipeResolver();
|
||||||
var cache = new CompilerCache();
|
var cache = new CompilerCache();
|
||||||
var viewResolver = new MultipleViewResolver(
|
var viewResolver = new MultipleViewResolver(
|
||||||
count, [BenchmarkComponentNoBindings, BenchmarkComponentWithBindings]);
|
count, [BenchmarkComponentNoBindings, BenchmarkComponentWithBindings]);
|
||||||
@ -46,9 +48,9 @@ export function main() {
|
|||||||
var renderCompiler = new DefaultDomCompiler(
|
var renderCompiler = new DefaultDomCompiler(
|
||||||
new DomElementSchemaRegistry(), new TemplateCloner(-1), new Parser(new Lexer()),
|
new DomElementSchemaRegistry(), new TemplateCloner(-1), new Parser(new Lexer()),
|
||||||
new ViewLoader(null, null, null), new SharedStylesHost(), 'a');
|
new ViewLoader(null, null, null), new SharedStylesHost(), 'a');
|
||||||
var compiler =
|
var compiler = new Compiler(reader, pipeResolver, [], cache, viewResolver,
|
||||||
new Compiler(reader, cache, viewResolver, new ComponentUrlMapper(), urlResolver,
|
new ComponentUrlMapper(), urlResolver, renderCompiler,
|
||||||
renderCompiler, new ProtoViewFactory(new DynamicChangeDetection()), appRootUrl);
|
new ProtoViewFactory(new DynamicChangeDetection()), appRootUrl);
|
||||||
|
|
||||||
function measureWrapper(func, desc) {
|
function measureWrapper(func, desc) {
|
||||||
return function() {
|
return function() {
|
||||||
|
@ -101,7 +101,7 @@ module.exports = function makeBrowserTree(options, destinationPath) {
|
|||||||
declaration: true,
|
declaration: true,
|
||||||
emitDecoratorMetadata: true,
|
emitDecoratorMetadata: true,
|
||||||
mapRoot: '', // force sourcemaps to use relative path
|
mapRoot: '', // force sourcemaps to use relative path
|
||||||
noEmitOnError: true,
|
noEmitOnError: false,
|
||||||
rootDir: '.',
|
rootDir: '.',
|
||||||
sourceMap: true,
|
sourceMap: true,
|
||||||
sourceRoot: '.',
|
sourceRoot: '.',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user