浏览代码

[core] Fix pre-selection issue with the select2 binding

This takes care of an issue that occur when the value and options of a select2 binding are independently updated in the same ko update cycle. If the selected value is updated before the options the select2 binding changes the selected value to empty, overwriting the new value, and once the options are updated the original value is no longer there.

With this change it will now refresh both the options and the selected value at the same time when any of them mutate.
Johan Ahlen 10 年之前
父节点
当前提交
7b22eede63

+ 39 - 3
desktop/core/src/desktop/static/desktop/js/ko.hue-bindings.js

@@ -1239,6 +1239,37 @@
   ko.bindingHandlers.select2 = {
     init: function (element, valueAccessor, allBindingsAccessor, vm) {
       var options = ko.toJS(valueAccessor()) || {};
+      var $element = $(element);
+
+      // When the options are in the binding value accessor the data attribute will be used instead of any <select>
+      // tag it's attached to.
+      if (ko.isObservable(valueAccessor().options) && ko.isObservable(valueAccessor().value)) {
+        var optionsObservable = valueAccessor().options;
+        var valueObservable = valueAccessor().value;
+        options.data = $.map(optionsObservable(), function (value) {
+          return { id: value, text: value }
+        });
+        options.val = valueObservable();
+
+        var refreshSelect2Data = function () {
+          $element.select2("data", $.map(optionsObservable(), function (value) {
+            return { id: value, text: value }
+          }));
+          $element.select2("val", valueObservable());
+        };
+
+        valueObservable.subscribe(function (newValue) {
+          if (newValue !== $element.select2("val")) {
+            refreshSelect2Data();
+          }
+        });
+
+        optionsObservable.subscribe(refreshSelect2Data);
+
+        window.setTimeout(function () {
+          refreshSelect2Data();
+        }, 10)
+      }
 
       if (typeof valueAccessor().update != "undefined") {
         if (options.type == "user" && viewModel.selectableHadoopUsers().indexOf(options.update) == -1) {
@@ -1283,11 +1314,16 @@
           }
         }
       }
-      $(element)
+      $element
           .select2(options)
           .on("change", function (e) {
-            if (typeof e.val != "undefined" && typeof valueAccessor().update != "undefined") {
-              valueAccessor().update(e.val);
+            if (typeof e.val != "undefined") {
+              if (typeof valueAccessor().update != "undefined") {
+                valueAccessor().update(e.val);
+              }
+              if (typeof valueAccessor().value != "undefined") {
+                valueAccessor().value(e.val);
+              }
             }
           })
           .on("select2-focus", function (e) {

+ 1 - 1
desktop/core/src/desktop/templates/ko_components.mako

@@ -192,7 +192,7 @@ from desktop.views import _ko
       </li>
 
       <li data-bind="visible: ! hasErrors() && ! assistHelper.loading()" >
-        <select data-bind="options: assistHelper.availableDatabases, select2: { width: '100%', placeholder: '${ _ko("Choose a database...") }', update: assistHelper.activeDatabase }" class="input-medium" data-placeholder="${_('Choose a database...')}"></select>
+        <div data-bind="select2: { options: assistHelper.availableDatabases, value: assistHelper.activeDatabase, width: '100%', placeholder: '${ _ko("Choose a database...") }' }" class="input-medium" data-placeholder="${_('Choose a database...')}"></div>
       </li>
 
       <li class="center" data-bind="visible: assistHelper.loading()" >