change event on select with knockout binding, how can i know if its a real change

guy schaller picture guy schaller · Jun 18, 2012 · Viewed 156.2k times · Source

I am building a permissions UI, I have a list of permissions with a select list next to each permission. The permissions are represented by an observable array of objects which are bound to a select list:

<div data-bind="foreach: permissions">
     <div class="permission_row">
          <span data-bind="text: name"></span>
          <select data-bind="value: level, event:{ change: $parent.permissionChanged}">
                   <option value="0"></option>
                   <option value="1">R</option>
                   <option value="2">RW</option>
           </select>
      </div>
 </div>

Now the problem is this: the change event gets raised when the UI is just populating for the first time. I call my ajax function, get the permissions list and then the event get raised for each of the permission items. This is really not the behavior I want. I want it to be raised only when a user really picks out a new value for the permission in the select list, how can I do that?

Answer

Sarath picture Sarath · Dec 5, 2013

Actually you want to find whether the event is triggered by user or program , and its obvious that event will trigger while initialization.

The knockout approach of adding subscription won't help in all cases, why because in most of the model will be implemented like this

  1. init the model with undefined data , just structure (actual KO initilization)
  2. update the model with initial data (logical init like load JSON , get data etc)
  3. User interaction and updates

The actual step that we want to capture is changes in 3, but in second step subscription will get call , So a better way is to add to event change like

 <select data-bind="value: level, event:{ change: $parent.permissionChanged}">

and detected the event in permissionChanged function

this.permissionChanged = function (obj, event) {

  if (event.originalEvent) { //user changed

  } else { // program changed

  }

}