| 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;
|
| + }
|
| }
|
|
|