feat(pipes): support arguments in transform function
This commit is contained in:
parent
f0e962c55e
commit
600d53c68e
|
@ -240,6 +240,8 @@ export class ChangeDetectorJITGenerator {
|
|||
|
||||
_genPipeCheck(r: ProtoRecord): string {
|
||||
var context = this._localNames[r.contextIndex];
|
||||
var argString = r.args.map((arg) => this._localNames[arg]).join(", ");
|
||||
|
||||
var oldValue = this._fieldNames[r.selfIndex];
|
||||
var newValue = this._localNames[r.selfIndex];
|
||||
var change = this._changeNames[r.selfIndex];
|
||||
|
@ -259,7 +261,7 @@ export class ChangeDetectorJITGenerator {
|
|||
${pipe} = ${PIPE_REGISTRY_ACCESSOR}.get('${pipeType}', ${context}, ${cdRef});
|
||||
}
|
||||
|
||||
${newValue} = ${pipe}.transform(${context});
|
||||
${newValue} = ${pipe}.transform(${context}, [${argString}]);
|
||||
if (${oldValue} !== ${newValue}) {
|
||||
${newValue} = ${UTIL}.unwrapValue(${newValue});
|
||||
${change} = true;
|
||||
|
|
|
@ -233,10 +233,11 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
|
|||
|
||||
_pipeCheck(proto: ProtoRecord, throwOnChange: boolean) {
|
||||
var context = this._readContext(proto);
|
||||
var args = this._readArgs(proto);
|
||||
|
||||
var pipe = this._pipeFor(proto, context);
|
||||
var prevValue = this._readSelf(proto);
|
||||
|
||||
var currValue = pipe.transform(context);
|
||||
var currValue = pipe.transform(context, args);
|
||||
|
||||
if (!isSame(prevValue, currValue)) {
|
||||
currValue = ChangeDetectionUtil.unwrapValue(currValue);
|
||||
|
|
|
@ -16,12 +16,13 @@ import {
|
|||
} from 'angular2/src/facade/lang';
|
||||
|
||||
import {WrappedValue, Pipe, BasePipe, PipeFactory} from './pipe';
|
||||
import {ChangeDetectorRef} from '../change_detector_ref';
|
||||
|
||||
@CONST()
|
||||
export class IterableChangesFactory implements PipeFactory {
|
||||
supports(obj): boolean { return IterableChanges.supportsObj(obj); }
|
||||
|
||||
create(cdRef): Pipe { return new IterableChanges(); }
|
||||
create(cdRef: ChangeDetectorRef): Pipe { return new IterableChanges(); }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -89,7 +90,7 @@ export class IterableChanges extends BasePipe {
|
|||
}
|
||||
}
|
||||
|
||||
transform(collection): any {
|
||||
transform(collection, args: List<any> = null): any {
|
||||
if (this.check(collection)) {
|
||||
return WrappedValue.wrap(this);
|
||||
} else {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import {isBlank, isPresent, Json, CONST} from 'angular2/src/facade/lang';
|
||||
import {Pipe, BasePipe, PipeFactory} from './pipe';
|
||||
import {ChangeDetectorRef} from '../change_detector_ref';
|
||||
|
||||
/**
|
||||
* Implements json transforms to any object.
|
||||
|
@ -27,8 +28,8 @@ import {Pipe, BasePipe, PipeFactory} from './pipe';
|
|||
* @exportedAs angular2/pipes
|
||||
*/
|
||||
@CONST()
|
||||
export class JsonPipe extends BasePipe {
|
||||
transform(value): string { return Json.stringify(value); }
|
||||
export class JsonPipe extends BasePipe implements PipeFactory {
|
||||
transform(value, args: List<any> = null): string { return Json.stringify(value); }
|
||||
|
||||
create(cdRef): Pipe { return this }
|
||||
create(cdRef: ChangeDetectorRef): Pipe { return this }
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||
import {stringify, looseIdentical, isJsObject, CONST} from 'angular2/src/facade/lang';
|
||||
|
||||
import {ChangeDetectorRef} from '../change_detector_ref';
|
||||
import {WrappedValue, BasePipe, Pipe, PipeFactory} from './pipe';
|
||||
|
||||
/**
|
||||
|
@ -10,7 +10,7 @@ import {WrappedValue, BasePipe, Pipe, PipeFactory} from './pipe';
|
|||
export class KeyValueChangesFactory implements PipeFactory {
|
||||
supports(obj): boolean { return KeyValueChanges.supportsObj(obj); }
|
||||
|
||||
create(cdRef): Pipe { return new KeyValueChanges(); }
|
||||
create(cdRef: ChangeDetectorRef): Pipe { return new KeyValueChanges(); }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -31,7 +31,7 @@ export class KeyValueChanges extends BasePipe {
|
|||
|
||||
supports(obj): boolean { return KeyValueChanges.supportsObj(obj); }
|
||||
|
||||
transform(map): any {
|
||||
transform(map, args: List<any> = null): any {
|
||||
if (this.check(map)) {
|
||||
return WrappedValue.wrap(this);
|
||||
} else {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import {isString, StringWrapper, CONST} from 'angular2/src/facade/lang';
|
||||
import {Pipe} from './pipe';
|
||||
import {Pipe, PipeFactory} from './pipe';
|
||||
import {ChangeDetectorRef} from '../change_detector_ref';
|
||||
|
||||
/**
|
||||
* Implements lowercase transforms to text.
|
||||
|
@ -30,7 +31,7 @@ export class LowerCasePipe implements Pipe {
|
|||
|
||||
onDestroy(): void { this._latestValue = null; }
|
||||
|
||||
transform(value: string): string {
|
||||
transform(value: string, args: List<any> = null): string {
|
||||
if (this._latestValue !== value) {
|
||||
this._latestValue = value;
|
||||
return StringWrapper.toLowerCase(value);
|
||||
|
@ -44,8 +45,8 @@ export class LowerCasePipe implements Pipe {
|
|||
* @exportedAs angular2/pipes
|
||||
*/
|
||||
@CONST()
|
||||
export class LowerCaseFactory {
|
||||
export class LowerCaseFactory implements PipeFactory {
|
||||
supports(str): boolean { return isString(str); }
|
||||
|
||||
create(): Pipe { return new LowerCasePipe(); }
|
||||
create(cdRef: ChangeDetectorRef): Pipe { return new LowerCasePipe(); }
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import {isBlank, CONST} from 'angular2/src/facade/lang';
|
||||
import {Pipe, BasePipe, WrappedValue, PipeFactory} from './pipe';
|
||||
import {ChangeDetectorRef} from '../change_detector_ref';
|
||||
|
||||
/**
|
||||
* @exportedAs angular2/pipes
|
||||
|
@ -8,7 +9,7 @@ import {Pipe, BasePipe, WrappedValue, PipeFactory} from './pipe';
|
|||
export class NullPipeFactory implements PipeFactory {
|
||||
supports(obj): boolean { return NullPipe.supportsObj(obj); }
|
||||
|
||||
create(cdRef): Pipe { return new NullPipe(); }
|
||||
create(cdRef: ChangeDetectorRef): Pipe { return new NullPipe(); }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -21,7 +22,7 @@ export class NullPipe extends BasePipe {
|
|||
|
||||
supports(obj): boolean { return NullPipe.supportsObj(obj); }
|
||||
|
||||
transform(value): WrappedValue {
|
||||
transform(value, args: List<any> = null): WrappedValue {
|
||||
if (!this.called) {
|
||||
this.called = true;
|
||||
return WrappedValue.wrap(null);
|
||||
|
|
|
@ -46,7 +46,7 @@ export class ObservablePipe implements Pipe {
|
|||
}
|
||||
}
|
||||
|
||||
transform(obs: Observable): any {
|
||||
transform(obs: Observable, args: List<any> = null): any {
|
||||
if (isBlank(this._subscription)) {
|
||||
this._subscribe(obs);
|
||||
return null;
|
||||
|
@ -94,5 +94,5 @@ export class ObservablePipe implements Pipe {
|
|||
export class ObservablePipeFactory implements PipeFactory {
|
||||
supports(obs): boolean { return ObservableWrapper.isObservable(obs); }
|
||||
|
||||
create(cdRef): Pipe { return new ObservablePipe(cdRef); }
|
||||
create(cdRef: ChangeDetectorRef): Pipe { return new ObservablePipe(cdRef); }
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import {ABSTRACT, BaseException, CONST} from 'angular2/src/facade/lang';
|
||||
import {ChangeDetectorRef} from '../change_detector_ref';
|
||||
|
||||
/**
|
||||
* Indicates that the result of a {@link Pipe} transformation has changed even though the reference
|
||||
|
@ -43,7 +44,7 @@ var _wrappedIndex = 0;
|
|||
*
|
||||
* onDestroy() {}
|
||||
*
|
||||
* transform(value) {
|
||||
* transform(value, args = []) {
|
||||
* return `${value}${value}`;
|
||||
* }
|
||||
* }
|
||||
|
@ -54,7 +55,7 @@ var _wrappedIndex = 0;
|
|||
export interface Pipe {
|
||||
supports(obj): boolean;
|
||||
onDestroy(): void;
|
||||
transform(value: any): any;
|
||||
transform(value: any, args: List<any>): any;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -74,12 +75,12 @@ export interface Pipe {
|
|||
export class BasePipe implements Pipe {
|
||||
supports(obj): boolean { return true; }
|
||||
onDestroy(): void {}
|
||||
transform(value: any): any { return _abstract(); }
|
||||
transform(value: any, args: List<any>): any { return _abstract(); }
|
||||
}
|
||||
|
||||
export interface PipeFactory {
|
||||
supports(obs): boolean;
|
||||
create(cdRef): Pipe;
|
||||
create(cdRef: ChangeDetectorRef): Pipe;
|
||||
}
|
||||
|
||||
function _abstract() {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
|
||||
import {isBlank, isPresent, isPromise, CONST} from 'angular2/src/facade/lang';
|
||||
import {Pipe, WrappedValue} from './pipe';
|
||||
import {Pipe, PipeFactory, WrappedValue} from './pipe';
|
||||
import {ChangeDetectorRef} from '../change_detector_ref';
|
||||
|
||||
/**
|
||||
|
@ -45,7 +45,7 @@ export class PromisePipe implements Pipe {
|
|||
}
|
||||
}
|
||||
|
||||
transform(promise: Promise<any>): any {
|
||||
transform(promise: Promise<any>, args: List<any> = null): any {
|
||||
if (isBlank(this._sourcePromise)) {
|
||||
this._sourcePromise = promise;
|
||||
promise.then((val) => {
|
||||
|
@ -81,8 +81,8 @@ export class PromisePipe implements Pipe {
|
|||
* @exportedAs angular2/pipes
|
||||
*/
|
||||
@CONST()
|
||||
export class PromisePipeFactory {
|
||||
export class PromisePipeFactory implements PipeFactory {
|
||||
supports(promise): boolean { return isPromise(promise); }
|
||||
|
||||
create(cdRef): Pipe { return new PromisePipe(cdRef); }
|
||||
create(cdRef: ChangeDetectorRef): Pipe { return new PromisePipe(cdRef); }
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import {isString, StringWrapper, CONST} from 'angular2/src/facade/lang';
|
||||
import {Pipe} from './pipe';
|
||||
import {Pipe, PipeFactory} from './pipe';
|
||||
import {ChangeDetectorRef} from '../change_detector_ref';
|
||||
|
||||
/**
|
||||
* Implements uppercase transforms to text.
|
||||
|
@ -30,7 +31,7 @@ export class UpperCasePipe implements Pipe {
|
|||
|
||||
onDestroy(): void { this._latestValue = null; }
|
||||
|
||||
transform(value: string): string {
|
||||
transform(value: string, args: List<any> = null): string {
|
||||
if (this._latestValue !== value) {
|
||||
this._latestValue = value;
|
||||
return StringWrapper.toUpperCase(value);
|
||||
|
@ -44,8 +45,8 @@ export class UpperCasePipe implements Pipe {
|
|||
* @exportedAs angular2/pipes
|
||||
*/
|
||||
@CONST()
|
||||
export class UpperCaseFactory {
|
||||
export class UpperCaseFactory implements PipeFactory {
|
||||
supports(str): boolean { return isString(str); }
|
||||
|
||||
create(): Pipe { return new UpperCasePipe(); }
|
||||
create(cdRef: ChangeDetectorRef): Pipe { return new UpperCasePipe(); }
|
||||
}
|
||||
|
|
|
@ -181,7 +181,8 @@ class _ConvertAstIntoProtoRecords implements AstVisitor {
|
|||
|
||||
visitPipe(ast: BindingPipe): number {
|
||||
var value = ast.exp.visit(this);
|
||||
return this._addRecord(RecordType.PIPE, ast.name, ast.name, [], null, value);
|
||||
var args = this._visitAll(ast.args);
|
||||
return this._addRecord(RecordType.PIPE, ast.name, ast.name, args, null, value);
|
||||
}
|
||||
|
||||
visitKeyedAccess(ast: KeyedAccess): number {
|
||||
|
|
|
@ -28,7 +28,7 @@ export class CSSClass {
|
|||
}
|
||||
|
||||
onCheck(): void {
|
||||
var diff = this._pipe.transform(this._rawClass);
|
||||
var diff = this._pipe.transform(this._rawClass, null);
|
||||
if (isPresent(diff) && isPresent(diff.wrapped)) {
|
||||
if (diff.wrapped instanceof IterableChanges) {
|
||||
this._applyArrayChanges(diff.wrapped);
|
||||
|
|
|
@ -55,7 +55,7 @@ export class NgFor {
|
|||
}
|
||||
|
||||
onCheck() {
|
||||
var diff = this._pipe.transform(this._ngForOf);
|
||||
var diff = this._pipe.transform(this._ngForOf, null);
|
||||
if (isPresent(diff)) this._applyChanges(diff.wrapped);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ export class NgStyle {
|
|||
}
|
||||
|
||||
onCheck() {
|
||||
var diff = this._pipe.transform(this._rawStyle);
|
||||
var diff = this._pipe.transform(this._rawStyle, null);
|
||||
if (isPresent(diff) && isPresent(diff.wrapped)) {
|
||||
this._applyChanges(diff.wrapped);
|
||||
}
|
||||
|
|
|
@ -304,6 +304,8 @@ class _CodegenState {
|
|||
|
||||
String _genPipeCheck(ProtoRecord r) {
|
||||
var context = _localNames[r.contextIndex];
|
||||
var argString = r.args.map((arg) => this._localNames[arg]).join(", ");
|
||||
|
||||
var oldValue = _fieldNames[r.selfIndex];
|
||||
var newValue = _localNames[r.selfIndex];
|
||||
var change = _changeNames[r.selfIndex];
|
||||
|
@ -322,7 +324,7 @@ class _CodegenState {
|
|||
$pipe = $_PIPE_REGISTRY_ACCESSOR.get('$pipeType', $context, $cdRef);
|
||||
}
|
||||
|
||||
$newValue = $pipe.transform($context);
|
||||
$newValue = $pipe.transform($context, [$argString]);
|
||||
if (!$_IDENTICAL_CHECK_FN($oldValue, $newValue)) {
|
||||
$newValue = $_UTIL.unwrapValue($newValue);
|
||||
$change = true;
|
||||
|
|
|
@ -300,6 +300,7 @@ var _availableDefinitions = [
|
|||
'{z: 1}',
|
||||
'{z: a}',
|
||||
'name | pipe',
|
||||
"name | pipe:'one':address.city",
|
||||
'value',
|
||||
'a',
|
||||
'address.city',
|
||||
|
|
|
@ -333,6 +333,15 @@ export function main() {
|
|||
val.changeDetector.detectChanges();
|
||||
expect(val.dispatcher.loggedValues).toEqual(['bob state:0']);
|
||||
});
|
||||
|
||||
it('should support arguments in pipes', () => {
|
||||
var registry = new FakePipeRegistry('pipe', () => new MultiArgPipe());
|
||||
var address = new Address('two');
|
||||
var person = new Person('value', address);
|
||||
var val = _createChangeDetector("name | pipe:'one':address.city", person, registry);
|
||||
val.changeDetector.detectChanges();
|
||||
expect(val.dispatcher.loggedValues).toEqual(['value one two default']);
|
||||
});
|
||||
});
|
||||
|
||||
it('should notify the dispatcher on all changes done', () => {
|
||||
|
@ -861,7 +870,7 @@ class CountingPipe implements Pipe {
|
|||
|
||||
supports(newValue) { return true; }
|
||||
|
||||
transform(value) { return `${value} state:${this.state ++}`; }
|
||||
transform(value, args = null) { return `${value} state:${this.state ++}`; }
|
||||
}
|
||||
|
||||
class OncePipe implements Pipe {
|
||||
|
@ -872,7 +881,7 @@ class OncePipe implements Pipe {
|
|||
|
||||
onDestroy() { this.destroyCalled = true; }
|
||||
|
||||
transform(value) {
|
||||
transform(value, args = null) {
|
||||
this.called = true;
|
||||
return value;
|
||||
}
|
||||
|
@ -883,7 +892,7 @@ class IdentityPipe implements Pipe {
|
|||
|
||||
onDestroy() {}
|
||||
|
||||
transform(value) { return value; }
|
||||
transform(value, args = null) { return value; }
|
||||
}
|
||||
|
||||
class WrappedPipe implements Pipe {
|
||||
|
@ -891,7 +900,18 @@ class WrappedPipe implements Pipe {
|
|||
|
||||
onDestroy() {}
|
||||
|
||||
transform(value) { return WrappedValue.wrap(value); }
|
||||
transform(value, args = null) { return WrappedValue.wrap(value); }
|
||||
}
|
||||
|
||||
class MultiArgPipe implements Pipe {
|
||||
transform(value, args = null) {
|
||||
var arg1 = args[0];
|
||||
var arg2 = args[1];
|
||||
var arg3 = args.length > 2 ? args[2] : 'default';
|
||||
return `${value} ${arg1} ${arg2} ${arg3}`;
|
||||
}
|
||||
supports(obj): boolean { return true; }
|
||||
onDestroy(): void {}
|
||||
}
|
||||
|
||||
class FakePipeRegistry extends PipeRegistry {
|
||||
|
|
|
@ -1473,7 +1473,7 @@ class DoublePipe implements Pipe {
|
|||
|
||||
supports(obj) { return true; }
|
||||
|
||||
transform(value) { return `${value}${value}`; }
|
||||
transform(value, args = null) { return `${value}${value}`; }
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
|
|
Loading…
Reference in New Issue