Hakan Fıstık
Hakan Fıstık

Reputation: 19421

bootstrap Dual Listbox knockout binding

I am using bootstrap dual listbox pluging in my ASP.NET MVC project.
I am also using Knockout in the project. I am trying to create bindingHandler for the this plugin to make it working smoothly with knockout.

here is what I tried

Binding Handler

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>

View Model

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());
    }
}

My problem is that I can not make sync between the viewModel observableArray, and the plugin. In other words, I want the changes in the plugin (the user removed some options or added some options) to be reflected on the view model property, and vice verse

Upvotes: 0

Views: 1420

Answers (1)

Ja9ad335h
Ja9ad335h

Reputation: 5075

to sync, you need to pass multiple observables to custom binding

so your html should be like

<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>

and custom binding be like

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

also i have created a dirty working jsfiddle

Upvotes: 2

Related Questions