Liran Friedman
Liran Friedman

Reputation: 4287

How to bind change event for checkbox in knockout js?

I'm using bootstrap switch to show checkbox as a switch and I want to bind a function to this switch, so the click data bind does not help here because the checkbox is not being clicked. So I probably need a "change" data bind like the onChange event that the checkbox have, but it didn't work when I tried to data bind change event to the checkbox...

Here is my data bind:

<input type="checkbox" onText="Active" offText="Inactive" 
       data-bind="bootstrapSwitchOn: ActiveFlag, change: function() { UpdateStatus() }" />

The switch is renders the checkbox like this:

<div class="has-switch" tabindex="0"
     <div class="switch-on">
          <span class="switch-left">Active</span
          <label>&nbsp;</label
          <span class="switch-right">Inactive</span>
          <input type="checkbox" ontext="Active" offtext="Inactive"
                 data-bind="bootstrapSwitchOn: ActiveFlag, change: function() { UpdateStatus() }">
     </div>
</div>

The checkbox gets display:"none" so it is not clicked but its state does change when clicking the switch

Upvotes: 2

Views: 2656

Answers (1)

Anish Patel
Anish Patel

Reputation: 4392

Expanding on my comment:

  1. You have an observable called ActiveFlag bound to the bootstrapSwitchOn binding which is updated when the bootstrap switch is toggled.
  2. And Knockoutjs has the facility to allow you to register callbacks to changes on observables.

With the these to points in mind, if you have an observable that is bound to changes to your toggle and you want to call some function when this toggle changes then you can register a your function as a callback to listen to the changes of the observable.

Hopefully, this snippet can explain this logic:

/**
 * Knockout binding handler for bootstrapSwitch indicating the status
 * of the switch (on/off): https://github.com/nostalgiaz/bootstrap-switch
 */
ko.bindingHandlers.bootstrapSwitchOn = {
  init: function(element, valueAccessor, allBindingsAccessor, viewModel) {
    $elem = $(element);
    $(element).bootstrapSwitch();
    $(element).bootstrapSwitch('setState', ko.utils.unwrapObservable(valueAccessor())); // Set intial state
    $elem.on('switch-change', function(e, data) {
      valueAccessor()(data.value);
    }); // Update the model when changed.
  },
  update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
    var vStatus = $(element).bootstrapSwitch('state');
    var vmStatus = ko.utils.unwrapObservable(valueAccessor());
    if (vStatus != vmStatus) {
      $(element).bootstrapSwitch('setState', vmStatus);
    }
  }
};

// your viewmodel bound to the web page

var vm = function() {
  this.log = ko.observableArray([]);

  // ActiveFlag observable bound to switch, synced with state of switch
  this.ActiveFlag = ko.observable(false);

  // the function I want to call whenever the switch state changes
  var doSomethingWhenSwitchStateChanges = function(value) {
    this.log.push('the switch state changed to: ' + value);
  }.bind(this);

  // register callback
  var subscription = this.ActiveFlag.subscribe(doSomethingWhenSwitchStateChanges);

}

ko.applyBindings(new vm());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-switch/2.0.0/css/bootstrap-switch.min.css" rel="stylesheet" />

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.0.3/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-switch/2.0.0/js/bootstrap-switch.min.js"></script>


<div class="row">
  <div class="col-md-6">
    <div>
      <input type="checkbox" data-bind="checked: ActiveFlag" />
    </div>
    <div>
      <input type="checkbox" data-bind="bootstrapSwitchOn: ActiveFlag" />
    </div>
  </div>
  <div class="col-md-6" data-bind="foreach: log">
    <p data-bind="text: $data"><p>
  </div>
</div>

Upvotes: 1

Related Questions