bootstrap 双列表框剔除绑定

bootstrap Dual Listbox knockout binding

我在 ASP.NET MVC 项目中使用 bootstrap dual listbox pluging
我也在项目中使用了Knockout。我正在尝试为这个插件创建 bindingHandler 以使其与 knockout 一起顺利工作。

这是我试过的

绑定处理程序

ko.bindingHandlers.dualList = {
    init: function (element, valueAccessor) {
        $(element).bootstrapDualListbox({
            selectorMinimalHeight: 160
        });

        $(element).on('change', function () {
            $(element).bootstrapDualListbox('refresh', true);
        });

        ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
            $(element).bootstrapDualListbox('destroy');
        });
    },
    update: function (element, valueAccessor) {
        $(element).bootstrapDualListbox('refresh', true);
    }
}

HTML

<select class="form-control" data-bind="foreach:{data: EditedElement().Operations, as : 'op'} , dualList: EditedElement().Operations" multiple>
    <option data-bind="value: op.OperationID(), text: op.Name(), selected: op.IsSelected()"></option>
</select>

查看模型

function SelectOperationVM(operationId, isSelected, name) {
    var self = this;

    self.OperationID = ko.observable(operationId);
    self.IsSelected = ko.observable(isSelected);
    self.Name = ko.observable(name);

    self.copy = function () {
        return new SelectOperationVM(self.OperationID(), self.IsSelected(), self.Name());
    }
}

我的问题是我无法在 viewModel observableArray 和插件之间进行同步。 换句话说,我希望插件中的更改(用户删除了一些选项或添加了一些选项)反映在视图模型 属性 上,反之亦然

要同步,您需要将多个可观察对象传递给自定义绑定

所以你的 html 应该像

<select class="form-control" data-bind="foreach: { data: Operations, as: 'op'}, dualList: { options: Operations, selected: Selected }" multiple>
    <option data-bind="value: op.OperationID(), text: op.Name(), selected: op.IsSelected()"></option>
</select>

自定义绑定就像

ko.bindingHandlers.dualList = {
  init: function(element, valueAccessor) {
    var data = ko.utils.unwrapObservable(valueAccessor());
    $(element).bootstrapDualListbox({
      selectorMinimalHeight: 160
    });

    $(element).on('change', function() {
      // save selected to an observable  
      data.selected($(element).val());;
    });

    ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
      $(element).bootstrapDualListbox('destroy');
    });
  },
  update: function(element, valueAccessor) {
    // to view if there is an update (without this "update" will not fire)
    var options = ko.utils.unwrapObservable(valueAccessor()).options();
    $(element).bootstrapDualListbox('refresh', true);
  }
}

我也创造了一个肮脏的工作jsfiddle