forked from dart-archive/angular.dart
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(filters): add filters in support of pure fields and methods, and…
… to observe lists and maps Closes dart-archive#359, dart-archive#394, dart-archive#397, dart-archive#757. Relates to dart-archive#772, dart-archive#773.
- Loading branch information
Showing
4 changed files
with
133 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
part of angular.filter; | ||
|
||
/** | ||
* This filter returns its argument unchanged but, for `List` and `Map` | ||
* arguments, it causes the argument contents to be observed (as opposed to | ||
* only its identity). | ||
* | ||
* Example: | ||
* | ||
* {{ list | observe }} | ||
*/ | ||
@NgFilter(name: 'observe') | ||
class ObserveFilter implements Function { | ||
dynamic call(dynamic _) => _; | ||
} | ||
|
||
/** | ||
* This filter returns the argument's value of the named field. Use this only | ||
* when the field get operation is known to be pure (side-effect free). | ||
* | ||
* Examples: | ||
* | ||
* {{ map | field:'keys' }} | ||
* {{ map | field:'values' }} | ||
* {{ list | field:'reversed' }} | ||
*/ | ||
@NgFilter(name: 'field') | ||
class GetPureFieldFilter implements Function { | ||
dynamic call(Object o, String fieldName) => | ||
o == null ? null : | ||
reflect(o).getField(new Symbol(fieldName)).reflectee; | ||
} | ||
|
||
/** | ||
* This filter returns the result of invoking the named method on the filter | ||
* argument. Use this only when the method is known to be pure (side-effect free). | ||
* | ||
* Examples: | ||
* | ||
* <span>{{ expression | method:'toString' }}</span> | ||
* <ul><li ng-repeat="n in (names | method:'split':[','])">{{n}}</li></ul> | ||
* | ||
* The first example is useful when _expression_ yields a new identity but its | ||
* string rendering is unchanged. | ||
*/ | ||
@NgFilter(name: 'method') | ||
class ApplyPureMethodFilter implements Function { | ||
dynamic call(Object o, String methodName, [args, Map<String,dynamic> namedArgs]) { | ||
if (o == null) return null; | ||
|
||
if (args is Map) { | ||
namedArgs = args; | ||
args = const []; | ||
} else if (args == null) { | ||
args = const []; | ||
} | ||
final Map<Symbol,dynamic> _namedArgs = namedArgs == null ? | ||
const <Symbol,dynamic>{} : <Symbol,dynamic>{}; | ||
if (namedArgs != null) { | ||
namedArgs.forEach((k,v) => _namedArgs[new Symbol(k)] = v); | ||
} | ||
return reflect(o).invoke(new Symbol(methodName), args, _namedArgs).reflectee; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
library pure_spec; | ||
|
||
import '../_specs.dart'; | ||
|
||
void main() { | ||
describe('pure filters', () { | ||
beforeEach((Scope scope, Parser parse, FilterMap filters) { | ||
scope.context['string'] = 'abc'; | ||
scope.context['list'] = 'abc'.split(''); | ||
scope.context['map'] = { 'a': 1, 'b': 2, 'c': 3 }; | ||
}); | ||
|
||
// Note that the `observe` filter is tested in [scope_spec.dart]. | ||
|
||
it('should return the value of the named field', | ||
(Scope scope, Parser parse, FilterMap filters) { | ||
expect(parse("list | field:'reversed'").eval(scope.context, filters) | ||
).toEqual(['c', 'b', 'a']); | ||
expect(parse("map | field:'keys'").eval(scope.context, filters)).toEqual( | ||
['a', 'b', 'c']); | ||
expect(parse("map | field:'values'").eval(scope.context, filters) | ||
).toEqual([1, 2, 3]); | ||
}); | ||
|
||
it('should return method call result', | ||
(Scope scope, Parser parse, FilterMap filters) { | ||
expect(parse("list | method:'toString'").eval(scope.context, filters) | ||
).toEqual('[a, b, c]'); | ||
expect(parse("list | method:'join':['']").eval(scope.context, filters) | ||
).toEqual('abc'); | ||
expect(parse("string | method:'split':['']").eval(scope.context, filters) | ||
).toEqual(['a', 'b', 'c']); | ||
}); | ||
|
||
it('should return method call result using namedArgs', | ||
(Scope scope, Parser parse, FilterMap filters) { | ||
scope.context['isB'] = (s) => s == 'b'; | ||
scope.context['zero'] = () => 0; | ||
|
||
// Test for no positional args but with named args. | ||
expect(parse("list | method:'toList':{'growable':false}").eval( | ||
scope.context, filters)).toEqual(['a', 'b', 'c']); | ||
|
||
// Test for both positional and named args. | ||
expect(parse("list | method:'firstWhere':[isB]:{'orElse':zero}").eval( | ||
scope.context, filters)).toEqual('b'); | ||
}); | ||
}); | ||
} |