diff --git a/example/web/bouncing_balls.dart b/example/web/bouncing_balls.dart index 30e3288b1..2861dc1f2 100644 --- a/example/web/bouncing_balls.dart +++ b/example/web/bouncing_balls.dart @@ -117,8 +117,10 @@ class BallPositionDirective { var style = element.style; style.backgroundColor = model.color; scope - ..watch('x', (x, _) => style.left = px(x), context: model, readOnly: true) - ..watch('y', (y, _) => style.top = px(y), context: model, readOnly: true); + ..watch('x', (x, _) => element.style.left = '${x + 10}px', + context: model, canChangeModel: false) + ..watch('y', (y, _) => element.style.top = '${y + 10}px', + context: model, canChangeModel: false); } } diff --git a/lib/core/scope.dart b/lib/core/scope.dart index 828713dcd..730acf447 100644 --- a/lib/core/scope.dart +++ b/lib/core/scope.dart @@ -192,17 +192,20 @@ class Scope { /** * Use [watch] to set up a watch in the [apply] cycle. * - * When [readOnly] is [:true:], the watch will be executed in the [flush] - * cycle. It should be used when the [reactionFn] does not change the model - * and allows the [digest] phase to converge faster. + * When [canChangeModel] is [:false:], the watch will be executed in the + * [flush] cycle. It should be used when the [reactionFn] does not change the + * model and allows speeding up the [digest] phase. * - * On the opposite, [readOnly] should be set to [:false:] if the [reactionFn] - * could change the model so that the watch is observed in the [digest] cycle. + * On the opposite, [canChangeModel] should be set to [:true:] if the + * [reactionFn] could change the model so that the watch is evaluated in the + * [digest] cycle. */ - Watch watch(String expression, ReactionFn reactionFn, {context, - FilterMap filters, bool readOnly: false, bool collection: false}) { + Watch watch(String expression, ReactionFn reactionFn, {context, + FilterMap filters, bool canChangeModel: true, bool collection: false}) { assert(isAttached); assert(expression is String); + assert(canChangeModel is bool); + Watch watch; ReactionFn fn = reactionFn; if (expression.isEmpty) { @@ -224,7 +227,8 @@ class Scope { AST ast = rootScope._astParser(expression, context: context, filters: filters, collection: collection); - WatchGroup group = readOnly ? _readOnlyGroup : _readWriteGroup; + + WatchGroup group = canChangeModel ? _readWriteGroup : _readOnlyGroup; return watch = group.watch(ast, fn); } diff --git a/lib/core_dom/ng_mustache.dart b/lib/core_dom/ng_mustache.dart index 60fbbe258..b727169dc 100644 --- a/lib/core_dom/ng_mustache.dart +++ b/lib/core_dom/ng_mustache.dart @@ -12,7 +12,10 @@ class NgTextMustacheDirective { FilterMap filters) { String expression = interpolate(template); - scope.watch(expression, _updateMarkup, readOnly: true, filters: filters); + scope.watch(expression, + _updateMarkup, + canChangeModel: false, + filters: filters); } void _updateMarkup(text, previousText) { @@ -45,7 +48,7 @@ class NgAttrMustacheDirective { _hasObservers = hasObservers; if (_watch != null) _watch.remove(); _watch = scope.watch(expression, _updateMarkup, filters: filters, - readOnly: !_hasObservers); + canChangeModel: _hasObservers); } }); } diff --git a/lib/directive/ng_class.dart b/lib/directive/ng_class.dart index fbe33464e..996ae17f9 100644 --- a/lib/directive/ng_class.dart +++ b/lib/directive/ng_class.dart @@ -173,7 +173,7 @@ abstract class _NgClassBase { currentSet = _flatten(current); _handleChange(scope.context[r'$index']); }, - readOnly: true, + canChangeModel: false, collection: true); if (mode != null) { @@ -186,7 +186,7 @@ abstract class _NgClassBase { previousSet.forEach((css) => _animate.removeClass(element, css)); } } - }, readOnly: true); + }, canChangeModel: false); } } diff --git a/lib/directive/ng_style.dart b/lib/directive/ng_style.dart index efbb6e3b4..566ba946b 100644 --- a/lib/directive/ng_style.dart +++ b/lib/directive/ng_style.dart @@ -27,8 +27,8 @@ class NgStyleDirective { set styleExpression(String value) { _styleExpression = value; if (_watch != null) _watch.remove(); - _watch = _scope.watch(_styleExpression, _onStyleChange, readOnly: true, - collection: true); + _watch = _scope.watch(_styleExpression, _onStyleChange, collection: true, + canChangeModel: false); } _onStyleChange(MapChangeRecord mapChangeRecord, _) { diff --git a/test/core/scope_spec.dart b/test/core/scope_spec.dart index 15a0277ed..4364ff755 100644 --- a/test/core/scope_spec.dart +++ b/test/core/scope_spec.dart @@ -862,7 +862,7 @@ void main() { it(r'should apply expression with full lifecycle', (RootScope rootScope) { var log = ''; var child = rootScope.createChild({"parent": rootScope.context}); - rootScope.watch('a', (a, _) { log += '1'; }, readOnly: true); + rootScope.watch('a', (a, _) { log += '1'; }, canChangeModel: false); child.apply('parent.a = 0'); expect(log).toEqual('1'); }); @@ -871,7 +871,7 @@ void main() { it(r'should schedule domWrites and domReads', (RootScope rootScope) { var log = ''; var child = rootScope.createChild({"parent": rootScope.context}); - rootScope.watch('a', (a, _) { log += '1'; }, readOnly: true); + rootScope.watch('a', (a, _) { log += '1'; }, canChangeModel: false); child.apply('parent.a = 0'); expect(log).toEqual('1'); }); @@ -884,7 +884,7 @@ void main() { beforeEach((RootScope rootScope) { rootScope.context['log'] = () { log += 'digest;'; return null; }; log = ''; - rootScope.watch('log()', (v, o) => null, readOnly: true); + rootScope.watch('log()', (v, o) => null, canChangeModel: false); rootScope.digest(); log = ''; }); @@ -893,7 +893,7 @@ void main() { LoggingExceptionHandler exceptionHandler = e; var log = []; var child = rootScope.createChild({}); - rootScope.watch('a', (a, _) => log.add('1'), readOnly: true); + rootScope.watch('a', (a, _) => log.add('1'), canChangeModel: false); rootScope.context['a'] = 0; child.apply(() { throw 'MyError'; }); expect(log.join(',')).toEqual('1'); @@ -929,7 +929,8 @@ void main() { rootScope.context['logger'] = (name) { log(name); return retValue; }; rootScope.watch('logger("watch")', (n, v) => null); - rootScope.watch('logger("flush")', (n, v) => null, readOnly: true); + rootScope.watch('logger("flush")', (n, v) => null, + canChangeModel: false); // clear watches rootScope.digest(); @@ -1426,7 +1427,8 @@ void main() { rootScope.domWrite(() => logger('write3')); throw 'read1'; }); - rootScope.watch('value', (_, __) => logger('observe'), readOnly: true); + rootScope.watch('value', (_, __) => logger('observe'), + canChangeModel: false); rootScope.flush(); expect(logger).toEqual(['write1', 'write2', 'observe', 'read1', 'read2', 'write3']); expect(exceptionHandler.errors.length).toEqual(2);