Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1549)

Unified Diff: pkg/template_binding/lib/src/input_bindings.dart

Issue 52553007: fix selected index binding to not count microtasks (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/template_binding/lib/src/input_bindings.dart
diff --git a/pkg/template_binding/lib/src/input_bindings.dart b/pkg/template_binding/lib/src/input_bindings.dart
index 8e5b3b0c806be6557cc30b706673464dad33e1a4..06b744fba63386ccc3f211a8284646b72a087c82 100644
--- a/pkg/template_binding/lib/src/input_bindings.dart
+++ b/pkg/template_binding/lib/src/input_bindings.dart
@@ -128,42 +128,31 @@ class _CheckedBinding extends _InputBinding {
}
class _SelectBinding extends _InputBinding {
+ MutationObserver _onMutation;
+
_SelectBinding(node, property, model, path)
: super(node, property, model, path);
SelectElement get node => super.node;
void valueChanged(newValue) {
- if (_tryUpdateValue(newValue)) return;
+ _cancelMutationObserver();
- // The binding may wish to bind to an <option> which has not yet been
- // produced by a child <template>. Furthermore, we may need to wait for
- // <optgroup> iterating and then for <option>.
- //
- // Unlike the JavaScript implemenation, we don't have a special
- // "Object.observe" event loop to schedule on.
- // (See the the "ensureScheduled" function:
- // https://github.com/Polymer/mdv/commit/9a51ad7ed74a292bf71662cea28acbd151ff65c8)
- //
- // Instead we use scheduleMicrotask. Each <template repeat> needs a delay of
- // 2:
- // * once to happen after the child _TemplateIterator is created
- // * once to be after _TemplateIterator's CompoundPathObserver resolve
- // And then we need to do this delay sequence twice:
- // * once for OPTGROUP
- // * once for OPTION.
- // The resulting 2 * 2 is our maxRetries.
- //
- // TODO(jmesserly): a much better approach would be to find the nested
- // <template> and wait on some future that completes when it has expanded.
- var maxRetries = 4;
Siggi Cherem (dart-lang) 2013/11/04 20:49:23 yay!
- delaySetSelectedIndex() {
- if (!_tryUpdateValue(newValue) && maxRetries-- > 0) {
- scheduleMicrotask(delaySetSelectedIndex);
- }
- }
+ if (_tryUpdateValue(newValue)) return;
- scheduleMicrotask(delaySetSelectedIndex);
+ // It could be that a template will expand an <option> child (or grandchild,
+ // if we have an <optgroup> in between). Since selected index cannot be set
+ // if the children aren't created yet, we need to wait for them to be
+ // created do this with a MutationObserver.
+ // Dart note: unlike JS we use mutation observers to avoid:
+ // https://github.com/Polymer/NodeBind/issues/5
+
+ // Note: it doesn't matter when the children get added; even if they get
+ // added much later, presumably we want the selected index data binding to
+ // still take effect.
+ _onMutation = new MutationObserver((x, y) {
+ if (_tryUpdateValue(value)) _cancelMutationObserver();
+ })..observe(node, childList: true, subtree: true);
}
bool _tryUpdateValue(newValue) {
@@ -177,7 +166,16 @@ class _SelectBinding extends _InputBinding {
}
}
+ void _cancelMutationObserver() {
+ if (_onMutation != null) {
+ _onMutation.disconnect();
+ _onMutation = null;
+ }
+ }
+
void nodeValueChanged(e) {
+ _cancelMutationObserver();
+
if (property == 'selectedIndex') {
value = node.selectedIndex;
} else if (property == 'value') {

Powered by Google App Engine
This is Rietveld 408576698