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

Commit

Permalink
feat(scope): Allow expressions on non-scope context
Browse files Browse the repository at this point in the history
  • Loading branch information
mhevery committed Feb 20, 2014
1 parent 195f043 commit e4dfb46
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 20 deletions.
21 changes: 12 additions & 9 deletions lib/core/scope.dart
Original file line number Diff line number Diff line change
Expand Up @@ -127,17 +127,19 @@ class Scope {
Scope(Object this.context, this.rootScope, this._parentScope, this._depth,
this._index, this.watchGroup, this.observeGroup);

Watch watch(expression, ReactionFn reactionFn) {
// Todo(misko): remove the parser from here. It should only take AST.
Watch watch(expression, ReactionFn reactionFn, {context, FilterMap filters}) {
assert(expression != null);
AST ast = expression is AST ? expression : rootScope._parse(expression);
AST ast = expression is AST
? expression
: rootScope._astParser(expression, context: context, filters: filters);
return watchGroup.watch(ast, reactionFn);
}

Watch observe(expression, ReactionFn reactionFn) {
// Todo(misko): remove the parser from here. It should only take AST.
Watch observe(expression, ReactionFn reactionFn, {context, FilterMap filters}) {
assert(expression != null);
AST ast = expression is AST ? expression : rootScope._parse(expression);
AST ast = expression is AST
? expression
: rootScope._astParser(expression, context: context, filters: filters);
return observeGroup.watch(ast, reactionFn);
}

Expand Down Expand Up @@ -218,6 +220,7 @@ class RootScope extends Scope {
static final STATE_FLUSH = 'digest';

final ExceptionHandler _exceptionHandler;
final AstParser _astParser;
final Parser _parser;
final ScopeDigestTTL _ttl;
final ExpressionVisitor visitor = new ExpressionVisitor(); // TODO(misko): delete me
Expand All @@ -229,8 +232,9 @@ class RootScope extends Scope {

String _state;

RootScope(Object context, this._parser, GetterCache cacheGetter,
FilterMap filterMap, this._exceptionHandler, this._ttl, this._zone)
RootScope(Object context, this._astParser, this._parser,
GetterCache cacheGetter, FilterMap filterMap,
this._exceptionHandler, this._ttl, this._zone)
: super(context, null, null, 0, 0,
new RootWatchGroup(new DirtyCheckingChangeDetector(cacheGetter), context),
new RootWatchGroup(new DirtyCheckingChangeDetector(cacheGetter), context))
Expand Down Expand Up @@ -357,7 +361,6 @@ class RootScope extends Scope {
}


AST _parse(expression) => visitor.visit(_parser.call(expression));
void destroy() {}

void _transitionState(String from, String to) {
Expand Down
24 changes: 14 additions & 10 deletions lib/core_dom/compiler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ part of angular.core.dom;
class Compiler {
final Profiler _perf;
final Parser _parser;
final AstParser _astParser;
final Expando _expando;

Compiler(this._perf, this._parser, this._astParser, this._expando);
Compiler(this._perf, this._parser, this._expando);

_compileBlock(NodeCursor domCursor, NodeCursor templateCursor,
List<DirectiveRef> useExistingDirectiveRefs,
Expand Down Expand Up @@ -160,25 +159,28 @@ class Compiler {
var blockOutbound = false;
var blockInbound = false;
scope.watch(
_astParser(expression, filters: filters),
expression,
(inboundValue, _) {
if (!blockInbound) {
blockOutbound = true;
scope.rootScope.runAsync(() => blockOutbound = false);
return dstPathFn.assign(controller, inboundValue);
}
}
},
filters: filters
);
if (expressionFn.isAssignable) {
scope.watch(
_astParser(dstExpression, context: controller, filters: filters),
dstExpression,
(outboundValue, _) {
if(!blockOutbound) {
blockInbound = true;
scope.rootScope.runAsync(() => blockInbound = false);
expressionFn.assign(scope.context, outboundValue);
}
}
},
context: controller,
filters: filters
);
}
};
Expand All @@ -188,8 +190,9 @@ class Compiler {
if (attrs[attrName] == null) return;
Expression attrExprFn = _parser(attrs[attrName]);
var shadowValue = null;
scope.watch(_astParser(attrs[attrName], filters: filters),
(v, _) => dstPathFn.assign(controller, shadowValue = v));
scope.watch(attrs[attrName],
(v, _) => dstPathFn.assign(controller, shadowValue = v),
filters: filters);
};
break;
case '=>!':
Expand All @@ -198,12 +201,13 @@ class Compiler {
Expression attrExprFn = _parser(attrs[attrName]);
var watch;
watch = scope.watch(
_astParser(attrs[attrName], filters: filters),
attrs[attrName],
(value, _) {
if (dstPathFn.assign(controller, value) != null) {
watch.remove();
}
});
},
filters: filters);
};
break;
case '&':
Expand Down
2 changes: 1 addition & 1 deletion lib/directive/input_select.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class InputSelectDirective implements NgAttachAware {
_selectElement.onChange.listen((event) => _mode.onViewChange(event));
_model.render = (value) {
// TODO(misko): this hack need to delay the rendering until after domRead
// becouse the modelChange reads from the DOM. We should be able to render
// because the modelChange reads from the DOM. We should be able to render
// without DOM changes.
_scope.rootScope.domRead(() {
_scope.rootScope.domWrite(() => _mode.onModelChange(value));
Expand Down
10 changes: 10 additions & 0 deletions test/core/scope_spec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,16 @@ main() => describe('scope', () {
}));


it('should watch/observe on objects other then contex', inject((RootScope rootScope) {
var log = '';
var map = {'a': 'A', 'b': 'B'};
rootScope.watch('a', (a, b) => log += a, context: map);
rootScope.watch('b', (a, b) => log += a, context: map);
rootScope.apply();
expect(log).toEqual('AB');
}));


it(r'should watch and fire on expression change', inject((RootScope rootScope) {
var log;

Expand Down

0 comments on commit e4dfb46

Please sign in to comment.