Skip to content
This repository has been archived by the owner on Feb 22, 2018. It is now read-only.

Commit

Permalink
feat(scope): Experimental: Watch once, watch not null expressions
Browse files Browse the repository at this point in the history
This is an experimental feature, and may not get into v1.0. Depend
on with caution.
  • Loading branch information
mhevery committed Feb 20, 2014
1 parent 443df96 commit 84762b1
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 9 deletions.
42 changes: 33 additions & 9 deletions lib/core/scope.dart
Original file line number Diff line number Diff line change
Expand Up @@ -173,19 +173,43 @@ class Scope {
* controller code you will most likely use [watch].
*/
Watch watch(expression, ReactionFn reactionFn, {context, FilterMap filters}) {
assert(expression != null);
AST ast = expression is AST
? expression
: rootScope._astParser(expression, context: context, filters: filters);
return watchGroup.watch(ast, reactionFn);
return _watch(watchGroup, expression, reactionFn, context, filters);
}

Watch observe(expression, ReactionFn reactionFn, {context, FilterMap filters}) {
return _watch(observeGroup, expression, reactionFn, context, filters);
}

Watch _watch(WatchGroup group, expression, ReactionFn reactionFn,
context, FilterMap filters) {
assert(expression != null);
AST ast = expression is AST
? expression
: rootScope._astParser(expression, context: context, filters: filters);
return observeGroup.watch(ast, reactionFn);
AST ast;
Watch watch;
ReactionFn fn = reactionFn;
if (expression is AST) {
ast = expression;
} else if (expression is String) {
if (expression.startsWith('::')) {
expression = expression.substring(2);
fn = (value, last) {
if (value != null) {
watch.remove();
return reactionFn(value, last);
}
};
} else if (expression.startsWith(':')) {
expression = expression.substring(1);
fn = (value, last) {
if (value != null) {
return reactionFn(value, last);
}
};
}
ast = rootScope._astParser(expression, context: context, filters: filters);
} else {
throw 'expressions must be String or AST got $expression.';
}
return watch = group.watch(ast, fn);
}

dynamic eval(expression, [Map locals]) {
Expand Down
28 changes: 28 additions & 0 deletions test/core/scope_spec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -984,6 +984,34 @@ main() => describe('scope', () {
}));
});


describe('special binding modes', () {
it('should bind one time', inject((RootScope rootScope, Logger log) {
rootScope.watch('foo', (v, _) => log('foo:$v'));
rootScope.watch(':foo', (v, _) => log(':foo:$v'));
rootScope.watch('::foo', (v, _) => log('::foo:$v'));

rootScope.apply();
expect(log).toEqual(['foo:null']);
log.clear();

rootScope.context['foo'] = true;
rootScope.apply();
expect(log).toEqual(['foo:true', ':foo:true', '::foo:true']);
log.clear();

rootScope.context['foo'] = 123;
rootScope.apply();
expect(log).toEqual(['foo:123', ':foo:123']);
log.clear();

rootScope.context['foo'] = null;
rootScope.apply();
expect(log).toEqual(['foo:null']);
log.clear();
}));
});


describe('runAsync', () {
it(r'should run callback before watch', inject((RootScope rootScope) {
Expand Down

0 comments on commit 84762b1

Please sign in to comment.