javascript - .Net Select/Select2 knockout javascript - 如果初始值不在下拉列表中,则无法加载初始值

标签 javascript jquery .net knockout.js jquery-select2

我想要一些有关“组合”框的 Select/Select2 功能的帮助,我正在尝试使用 knockout/jquery 在 .Net 中设置该框。我需要用一组值预加载此“组合”框,然后允许用户添加其他条目(从下拉列表中选择或输入其他内容)或删除条目。只要预加载到“组合”框中的值存在于协调下拉列表(所有用户)中,下面的代码就可以正常工作。如果下拉列表中不存在预加载的值,它们就会被绕过。

还有其他人必须处理这个问题吗?你是如何克服的?如果有任何反馈或想法,我将不胜感激!

<select data-bind="selectedOptions: newMessageTo, optionsCaption: 'Select a user...', 
    options: allUsers, optionsText: 'userName', optionsValue: 'userName', 
    select2: { placeholder: 'Select a user...', allowClear: true, multiple: true, 
    minimumInputLength: 3, tags: true, minimumResultsForSearch: 20 }">
</select>
self.myMessage = ko.observable({});
self.myMessageText = ko.observable("");
self.messageId = ko.observable({});
self.newMessageText = ko.observable("");
self.newMessageTo = ko.observableArray([]);
self.newMessageSubject = ko.observable("");
self.newAttachment = ko.observable({});
self.newAttachmentList = ko.observableArray([]);
self.allUsers = ko.observable({});
self.bearer = ko.observable();
self.newStyleAttachments = ko.observable(false);

self.replyAll = function () {
    self.replying() ? self.replying(false) : self.replying(true);
    self.newMessageTo.removeAll();
    for (var i = 0; i < self.myMessage().cc.length; i++) {
        if (self.myMessage().cc[i] !== self.user.email) {
            self.newMessageTo.push(self.myMessage().cc[i]);
        }
    }
    self.newMessageTo.push(self.myMessage().senderEmail);
    self.newMessageText("<br/><center>-------------------------------------------</center><br/> \
        <b>From:</b> " + self.myMessage().senderEmail + " <br/><b>To:</b> " + self.myMessage().cc + " \
        <br/><b>Subject:</b> " + self.myMessage().messageSubject + "<br/>" + self.myMessageText());
    self.newMessageSubject("RE: " + self.myMessage().messageSubject);
};
ko.bindingHandlers.select2 = {
    init: function (el, valueAccessor, allBindingsAccessor, viewModel) {
        ko.utils.domNodeDisposal.addDisposeCallback(el, function () {
            $(el).select2('destroy');
        });

        var allBindings = allBindingsAccessor(),
            select2 = ko.utils.unwrapObservable(allBindings.select2);

        $(el).select2(select2);
    },
    update: function (el, valueAccessor, allBindingsAccessor, viewModel) {
        var allBindings = allBindingsAccessor();

        if ("value" in allBindings) {
            if ((allBindings.select2.multiple || el.multiple) && allBindings.value().constructor != Array) {
                $(el).val(allBindings.value().split(',')).change();
            }
            else {
                $(el).val(allBindings.value()).change();
            }
        } else if ("selectedOptions" in allBindings) {
            var converted = [];
            var textAccessor = function (value) { return value; };
            if ("optionsText" in allBindings) {
                textAccessor = function (value) {
                    var valueAccessor = function (item) { return item; }
                    if ("optionsValue" in allBindings) {
                        valueAccessor = function (item) { return item[allBindings.optionsValue]; }
                    }
                    var items = $.grep(allBindings.options(), function (e) { return valueAccessor(e) == value });
                    if (items.length == 0 || items.length > 1) {
                        return "UNKNOWN";
                    }
                    return items[0][allBindings.optionsText];
                }
            }
            $.each(allBindings.selectedOptions(), function (key, value) {
                converted.push({ id: value, text: textAccessor(value) });
            });
            $(el).select2("data", converted);
        }
        $(el).change();
    }
};

最佳答案

我的猜测是,这与您的 select2 knockout 绑定(bind)有关(问题中不存在)。

下面是一个工作示例,其中包含一个非常简单的绑定(bind)处理程序,取自 here 。只需运行代码片段,该代码片段会预先填充 2 个选项和 1 个值的下拉列表,然后(5 秒后)向其中添加 2 个值 - 一个作为选项存在,另一个则不存在(因此也添加了作为一个新选项):

$(document).ready(function () {
  registerBinding();
  run();
});

var vm = function () {
  var self = this;
  self.available = ko.observableArray(['John', 'Joe']);
  self.selected = ko.observableArray(['John']);
  self.add = function (otherUsers) {
    otherUsers.forEach(function (otherUser) {
        var matchedAvailable = self.match(self.available(), otherUser);
        var matchedSelected = self.match(self.selected(), otherUser);
        if (!matchedAvailable) {
            self.available.push(otherUser);
        }
        if (!matchedSelected) {
            self.selected.push(otherUser);
        }
    });
  };
  self.match = function (users, userToMatch) {
      var matched = ko.utils.arrayFirst(users, function (user) {
          return user == userToMatch;
      });
      return matched;
  };
};

function run() {
  var vmInstance = new vm();
  ko.applyBindings(vmInstance);
  setTimeout(function () {
    vmInstance.add(['Jane', 'Joe']);
  }, 5000);
}

function registerBinding() {
  ko.bindingHandlers.select2 = {
      after: ["options", "value"],
      init: function (el, valueAccessor, allBindingsAccessor, viewModel) {
          $(el).select2(ko.unwrap(valueAccessor()));
          ko.utils.domNodeDisposal.addDisposeCallback(el, function () {
              $(el).select2('destroy');
          });
      },
      update: function (el, valueAccessor, allBindingsAccessor, viewModel) {
          var allBindings = allBindingsAccessor();
          var select2 = $(el).data("select2");
          if ("value" in allBindings) {
              var newValue = "" + ko.unwrap(allBindings.value);
              if ((allBindings.select2.multiple || el.multiple) && newValue.constructor !== Array) {
                  select2.val([newValue.split(",")]);
              }
              else {
                  select2.val([newValue]);
              }
          }
      }
  }
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.12/js/select2.full.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.12/css/select2.min.css" />

<div class="col-xs-4">
    <label for="users">Users</label>
    <select id="users" class="form-control"
            multiple="multiple"
            data-bind="options: available,
                selectedOptions: selected,
                select2: { placeholder: 'Select an option...', allowClear: true }">
    </select>
</div>

关于javascript - .Net Select/Select2 knockout javascript - 如果初始值不在下拉列表中,则无法加载初始值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59842041/

相关文章:

javascript - 使用 React 和 Django 处理许多 html 文件

javascript - AngularJS从base64生成二进制数据图像并作为图像文件发送到服务器

c# - 为什么 TcpClient 与构造函数中的参数连接速度较慢?

JavaScript 未在 Canvas 上绘图

javascript - jstree 插件和 stopPropagation 问题

javascript - 图表 js 不显示图表

javascript - 使用 nth-child CSS 定位异常数字

c# - CompileAssemblyFromDom 抛出 FileNotFoundException

.net - 如何从.NET解决方案构建 'dependency tree diagram'

javascript - AngularJS $location.search() 不工作