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