Index: pkg/polymer_expressions/lib/polymer_expressions.dart |
diff --git a/pkg/polymer_expressions/lib/polymer_expressions.dart b/pkg/polymer_expressions/lib/polymer_expressions.dart |
index 0d4d06192fe05ad9292a8e0f768e7f5b427f2d3e..36ea3524adbc8d7acfc4d1e2e8598353872a4eb7 100644 |
--- a/pkg/polymer_expressions/lib/polymer_expressions.dart |
+++ b/pkg/polymer_expressions/lib/polymer_expressions.dart |
@@ -81,17 +81,23 @@ class PolymerExpressions extends BindingDelegate { |
return null; |
} |
- return (model, node) { |
+ return (model, node, oneTime) { |
if (model is! Scope) { |
model = new Scope(model: model, variables: globals); |
} |
+ var converter = null; |
if (node is Element && name == "class") { |
- return new _Binding(expr, model, _classAttributeConverter); |
+ converter = _classAttributeConverter; |
} |
if (node is Element && name == "style") { |
- return new _Binding(expr, model, _styleAttributeConverter); |
+ converter = _styleAttributeConverter; |
} |
- return new _Binding(expr, model); |
+ |
+ if (oneTime) { |
+ return _Binding._oneTime(expr, model, converter); |
+ } |
+ |
+ return new _Binding(expr, model, converter); |
}; |
} |
@@ -99,50 +105,82 @@ class PolymerExpressions extends BindingDelegate { |
model is Scope ? model : new Scope(model: model, variables: globals); |
} |
-class _Binding extends ChangeNotifier { |
+class _Binding extends Bindable { |
final Scope _scope; |
- final ExpressionObserver _expr; |
final _converter; |
+ Expression _expr; |
+ Function _callback; |
+ StreamSubscription _sub; |
var _value; |
- _Binding(Expression expr, Scope scope, [this._converter]) |
- : _expr = observe(expr, scope), |
- _scope = scope { |
- _expr.onUpdate.listen(_setValue).onError((e) { |
- _logger.warning("Error evaluating expression '$_expr': ${e.message}"); |
- }); |
+ _Binding(this._expr, this._scope, [this._converter]); |
+ |
+ static _oneTime(Expression expr, Scope scope, [converter]) { |
try { |
- update(_expr, _scope); |
- _setValue(_expr.currentValue); |
+ return _convertValue(eval(expr, scope), scope, converter); |
} on EvalException catch (e) { |
- _logger.warning("Error evaluating expression '$_expr': ${e.message}"); |
+ _logger.warning("Error evaluating expression '$expr': ${e.message}"); |
+ return null; |
} |
} |
_setValue(v) { |
- var oldValue = _value; |
+ _value = _convertValue(v, _scope, _converter); |
+ if (_callback != null) _callback(_value); |
+ } |
+ |
+ static _convertValue(v, scope, converter) { |
if (v is Comprehension) { |
// convert the Comprehension into a list of scopes with the loop |
// variable added to the scope |
- _value = v.iterable.map((i) { |
+ return v.iterable.map((i) { |
var vars = new Map(); |
vars[v.identifier] = i; |
- Scope childScope = new Scope(parent: _scope, variables: vars); |
+ Scope childScope = new Scope(parent: scope, variables: vars); |
return childScope; |
}).toList(growable: false); |
} else { |
- _value = (_converter == null) ? v : _converter(v); |
+ return converter == null ? v : converter(v); |
} |
- notifyPropertyChange(#value, oldValue, _value); |
} |
- @reflectable get value => _value; |
+ get value { |
+ if (_callback != null) return _value; |
+ return _oneTime(_expr, _scope, _converter); |
+ } |
- @reflectable set value(v) { |
+ set value(v) { |
try { |
assign(_expr, v, _scope); |
} on EvalException catch (e) { |
_logger.warning("Error evaluating expression '$_expr': ${e.message}"); |
} |
} |
+ |
+ open(callback(value)) { |
+ if (_callback != null) throw new StateError('already open'); |
+ |
+ _callback = callback; |
+ final expr = observe(_expr, _scope); |
+ _expr = expr; |
+ _sub = expr.onUpdate.listen(_setValue)..onError((e) { |
+ _logger.warning("Error evaluating expression '$_expr': ${e.message}"); |
+ }); |
+ try { |
+ update(expr, _scope); |
+ _value = _convertValue(expr.currentValue, _scope, _converter); |
+ } on EvalException catch (e) { |
+ _logger.warning("Error evaluating expression '$_expr': ${e.message}"); |
+ } |
+ return _value; |
+ } |
+ |
+ void close() { |
+ if (_callback == null) return; |
+ |
+ _sub.cancel(); |
+ _sub = null; |
+ _expr = (_expr as ExpressionObserver).expression; |
+ _callback = null; |
+ } |
} |