简体   繁体   中英

Checkbox onclick in knockout is not updating viewmodel

I have list of check boxes, on click of any checkbox i need to get all checked check boxes. To do that I am calling the java script function "ChangeColumnSelection".

The issue is, the clicked check box is not updating view model immediately. When i click next text box, I am seeing that the previously check box value got updated in the view model.

 <ul class="list-group" data-bind="foreach: SelectionColumnList">
      <li class="list-group-item">
          <input type="checkbox" data-bind="attr: {onclick: 'javascript:ChangeColumnSelection(\'' + ColumnID + '\')'}, checked: IsSelected"
                        class="pull-xs-left push-down rightmargin" />
          <span data-bind="text: ColumnName"></span>
     </li>
 </ul>

Update:

My view model is

  var dynamicGridViewModel = {
        SelectionColumnList: ko.observableArray([])
   }; 

    selectionInfo.ColumnID = columnInfo.ColumnID;
    selectionInfo.ColumnName = columnInfo.ColumnName;
    selectionInfo.DisplayOrder = columnInfo.DisplayOrder;
    selectionInfo.SortType = 'None';
    selectionInfo.IsSelected = true;
    dynamicGridViewModel.SelectionColumnList.push(selectionInfo);

You don't need onclick events. You can achieve this just with checked binding :

 var array = [{ ColumnID: 1, ColumnName: "ColumnName 1" }, { ColumnID: 2, ColumnName: "ColumnName 2" }] var viewModel = function() { var self = this; self.SelectionColumnList = ko.observableArray(array); // no need to populate the array manually. Knockout will take care of it self.chosenItems = ko.observableArray(); // every time chosenItems array changes, subscribe callback function gets triggered self.chosenItems.subscribe(function() { console.log(self.chosenItems()); }) } ko.applyBindings(new viewModel()); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> <ul class="list-group" data-bind="foreach: SelectionColumnList"> <li class="list-group-item"> <input type="checkbox" data-bind="checkedValue: ColumnID, checked: $parent.chosenItems" /> <span data-bind="text: ColumnName"></span> </li> </ul> 

Here, ColumnId is set as the value of checkbox input. Hence, the chosenItems array will be an array of selected ColumnId s.

The great thing about Knockout is that, it allows not only primitive types like string, number or bool for checkedValue , but objects too. If you want the entire Column object to be populated in chosenItems , then you can set the checkedValue like this:

<input type="checkbox" data-bind="checkedValue: $data, checked: $parent.chosenItems" />

If you want to perform some operation upon changing of any checkbox's state, you can perform that inside the subscribe callback. This function gets triggered every time the array changes.

(Also, the proper way to add a click binding is data-bind="click: clickFunction" )

UPDATE:

You're using an object literal as your viewModel. I suggest you create viewModel function and use the new operator. If you want to bind checked to a boolean property of Column , then you can create a computed property and subscribe to that computed property:

 var columns = [{ ColumnID: 1, ColumnName: "ColumnName 1", IsSelected: false }, { ColumnID: 2, ColumnName: "ColumnName 2", IsSelected: true }]; var viewModel = function() { var self = this; self.SelectionColumnList = ko.observableArray([]); // this property has the selected ColumnIds self.selectedItems = ko.computed(() => { // If you're using ES6 systax // return self.SelectionColumnList() // .filter(column => column.IsSelected()) // .map(column => column.ColumnID); // out of the columns, get the ColumnIds with IsSelected as true return self.SelectionColumnList() .filter(function(column) { return column.IsSelected(); }) .map(function(column) { return column.ColumnID }); }); // gets triggered everytime checkbox is checked/unchecked self.selectedItems.subscribe(function() { console.log(self.selectedItems()); }); } // create a new instance of the viewmodel var dynamicGridViewModel = new viewModel(); // loop through the columns and populate the observableArray columns.forEach(function(columnInfo) { var selectionInfo = {}; selectionInfo.ColumnID = columnInfo.ColumnID; selectionInfo.ColumnName = columnInfo.ColumnName; // this property must be an observable selectionInfo.IsSelected = ko.observable(columnInfo.IsSelected); dynamicGridViewModel.SelectionColumnList.push(selectionInfo); }) ko.applyBindings(dynamicGridViewModel); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> <ul class="list-group" data-bind="foreach: SelectionColumnList"> <li class="list-group-item"> <input type="checkbox" data-bind="checked: IsSelected" /> <span data-bind="text: ColumnName"></span> </li> </ul> 

Here's a fiddle for testing

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM