This page shows how to get started with Wijmo's CollectionView class.
Wijmo has a solid infrastructure based on a powerful data layer that is familiar to
.NET developers. The main data binding interface is the
ICollectionView.
Wijmo includes several classes that implement ICollectionView. The most basic is the
CollectionView class,
which uses regular JavaScript arrays as data sources.
The CollectionView class implements the following interfaces:
ICollectionView: Provides current record management, custom sorting,
filtering, and grouping.
IEditableCollectionView: Provides methods for editing, adding, and
removing items.
IPagedCollectionView: Provides paging for navigating through large
numbers of items.
The CollectionView class can keep track of changes made to the data. This
feature is useful for submitting changes to the server.
Getting Started
To use the CollectionView class, start by declaring it and passing in a regular array as the data source.
Then access the CollectionView using the view model's collectionView property.
In this example, we show the CollectionView instance in a Wijmo FlexGrid.
Steps to getting started with the CollectionView class in KnockoutJS applications:
Add references to KnockoutJS, Wijmo, and the Wijmo KnockoutJS bindings.
Add table (or FlexGrid) to the page and bind it to the CollectionView data.
Add a view model to provide data and logic.
(Optional) Add some CSS to customize the grid's appearance.
function basicVM(data) {
this.collectionView = new wijmo.collections.CollectionView(data);
}
ko.applyBindings(new basicVM(dataSvc.getData(100)), document.getElementById('gettingStarted'));
Result (live):
Current Record Management
As implementing the interface ICollectionView, CollectionView can manage the current record.
This example shows how you can manage the current record through APIs provided by the CollectionView class.
In this case, we use the properties currentPosition to obtain the current record position in the collection.
We also use the methods moveCurrentTo(item), moveCurrentToFirst(), moveCurrentToLast(),
moveCurrentToNext(), moveCurrentToPosition(index) and moveCurrentToPrevious() to change the
current position. When the current is changed, we use the events currentChanging and currentChanged to
track it. We can cancel the current changing in the event currentChanging.
Notes: Click the "Move To Next" button to move the current to the next one. Click the "Move to Previous" to move the
current to the previous on. Clicking the "Stop in 4th Row" button will cause the current is forbidden to be changed
when it locates in the 4th row. Then clicking the "Clear Stopping" button will let the current be changed freely.
this.collectionView = new wijmo.collections.CollectionView(data);
this.addStopping = function () {
this.collectionView.currentChanging.addHandler(stoppingHandler);
};
this.clearStopping = function () {
this.collectionView.currentChanging.removeHandler(stoppingHandler);
};
function stoppingHandler (sender, args) {
if (sender.currentPosition === 3) {
args.cancel = true;
}
}
Result (live):
Sorting
The CollectionView class supports sorting through the ICollectionView interface, which is identical to the
one in .NET. To enable sorting, add one or more sortDescriptions objects to the CollectionView.sortDescriptions
property. Then the sorted result can be obtained from the CollectionView.items property.
SortDescription objects are flexible, allowing you to sort data based on value in ascending or descending order.
In the sample below, you can sort the collection based on the corresponding field value choosed in the first list. You can
also specify the sorting order in the second list.
this.collectionView = new wijmo.collections.CollectionView(data);
this.names = names;
this.currentSort = ko.observable();
this.currentSort.subscribe(applySort, this);
this.sortOrder = ko.observable();
this.sortOrder.subscribe(applySort, this);
// perform CollectionView sorting when dropdown value changes
function applySort(newVal) {
var currentSort = this.currentSort(),
sortOrder = this.sortOrder() === 'true',
cv = this.collectionView;
if (!currentSort) return;
cv.sortDescriptions.clear();
cv.sortDescriptions.push(new wijmo.collections.SortDescription(currentSort, sortOrder));
}
Result (live):
Filtering
The CollectionView class supports filtering through the ICollectionView interface, which is identical to
the one in .NET. To enable filtering, set the CollectionView.filter property to a function that determines which
objects to be included in the view.
In this example, we create a filter for the country, and get the filter value from the input control. When you input the
filter, the grid will be refreshed and render the fitlered data.
this.collectionView = new wijmo.collections.CollectionView(data);
this.collectionView.filter = filterFn.bind(this);
this.filterText = ko.observable('');
this.filterText.subscribe(function(newVal) {
this.collectionView.refresh();
}, this);
// function used to filter the CollectionView
function filterFn(dataItem) {
if (!this.hasOwnProperty('filterText')) return true;
var filterText = this.filterText().toLowerCase();
return !filterText || dataItem.country.toLowerCase().indexOf(filterText) > -1;
}
Result (live):
Grouping
The CollectionView class supports grouping through the ICollectionView interface, which is identical to the
one in .NET. To enable grouping, add one or more GroupDescription objects to the CollectionView.groupDescriptions
property, and ensure that the grid's showGroups property is set to true when creating the grid instance(the default
value is false.).
GroupDescription objects are flexible, allowing you to group data based on value or on grouping functions.
The example below groups the collection by the field which you select from the list. The grid shows not only the items content,
but also the group information: the group name and the average value of amount in the group.
Notes: Selecting one item in the list will add a new instance of GroupDescription. If the GroupDescription already exists,
nothing happens. In order to clear the group setting, select the first item in the list.
<div class="well">
<select class="form-control"
data-bind="options: names,
value: currentGroup,
optionsCaption: 'Please choose the field you wish to group by...'"></select>
</div>
<div data-bind="wjFlexGrid: { itemsSource: collectionView }"></div>
this.collectionView = new wijmo.collections.CollectionView(data);
this.names = names;
this.currentGroup = ko.observable();
this.currentGroup.subscribe(function (newVal) {
var currentGroup = newVal,
cv = this.collectionView;
// clear groups when the "placeholder" is selected
if (!currentGroup) {
cv.groupDescriptions.clear();
return;
}
// prevent double grouping
var exists = cv.groupDescriptions.some(function (item) {
return item.propertyName === currentGroup;
});
if (exists) return;
// perform grouping
cv.groupDescriptions.push(new wijmo.collections.PropertyGroupDescription(currentGroup));
}, this);
Result (live):
Editing
As implementing the interface IEditableCollectionView, the CollectionView class supports editing.
This sample shows how you can update, add, and remove the specified item in the collection.
In this sample, you can select the row in the grid and press the Edit Detail button to start editing. After finishing editing
in the popup dialog, press the OK button to commit your updating. If you want to add a new record to the collection, press the
Add button and customize the item content in the popup dialog. Then press the OK button to commit your adding. If you don't want
to update/add the record, just press the Cancel button in the dialog. Select the row and press the Delete button will let you
remove the record from the collection.
After updating, adding, and removing records, the grid will be refreshed accordingly.
var collectionView = new wijmo.collections.CollectionView(data);
collectionView.newItemCreator = function () {
// return object with an ID property
return {
id: wijmo.getAggregate(wijmo.Aggregate.Max, collectionView.sourceCollection, 'id') + 1
};
};
this.collectionView = ko.observable(collectionView);
this.currentItem = ko.computed(function () {
return this.collectionView().currentItem;
}, this);
this.addItem = function () {
collectionView.addNew();
};
// commit CollectionView's changes
this.commitUpdate = function () {
collectionView.commitEdit();
collectionView.commitNew();
collectionView.refresh();
};
// cancel CollectionView's changes
this.cancelUpdate = function () {
collectionView.cancelEdit();
collectionView.cancelNew();
collectionView.refresh();
};
collectionView.collectionChanged.addHandler(notifyChange.bind(this));
collectionView.currentChanged.addHandler(notifyChange.bind(this));
function notifyChange() {
this.collectionView.valueHasMutated();
}
Result (live):
Edit Item
Paging
The CollectionView class supports paging through the IPagedCollectionView interface, which is nearly identical
to the one in .NET. To enable paging, set the IPagedCollectionView.pageSize property to the number of items you want
on each page, and provide a UI for navigating the pages.
In this example, we use JavaScript to show 10 items per page. You can customize it in the text box. We add navigation buttons,
and call IPagedCollectionView methods in the button click. Note that we use the pageIndex and pageCount
properties to show the current page and total number of pages. You can customize the page size in the first text box. Let it be empty
or 0 to make CollectionView no paging. Then the navigation buttons will be invisible.
var collectionView = new wijmo.collections.CollectionView(data);
collectionView.pageSize = 10;
this.collectionView = ko.observable(collectionView);
// computed property to help get/set the CollectionView's pageSize property
this.pageSize = ko.computed({
read: function () {
return this.collectionView().pageSize;
},
write: function (newVal) {
this.collectionView().pageSize = Math.abs(parseInt(newVal)) || 0;
}
}, this);
// determine if previous/first page buttons should be disabled/enabled
this.isBeginning = ko.computed(function () {
return this.collectionView().pageIndex === 0;
}, this);
// determine if next/last page buttons should be disabled/enabled
this.isEnd = ko.computed(function () {
return (this.collectionView().pageIndex + 1) === this.collectionView().pageCount;
}, this);
collectionView.collectionChanged.addHandler(notifyChange.bind(this));
collectionView.currentChanged.addHandler(notifyChange.bind(this));
collectionView.pageChanged.addHandler(notifyChange.bind(this));
function notifyChange() {
this.collectionView.valueHasMutated();
}
Result (live):
Tracking Changes
The CollectionView class can keep track of changes made to the data. It is useful in situations where you must submit changes
to the server. To turn on change tracking, set the trackChanges property to true. Once you do that, the CollectionView
keeps track of any changes made to the data and exposes them in three arrays:
itemsEdited: This list contains items that are edited using the beginEdit and commitEdit methods.
itemsAdded: This list contains items that are added using the addNew and commitNew methods.
itemsRemoved: This list contains items that are removed using the remove method.
This feature is demonstrated below using a FlexGrid. The grid is bound to a CollectionView with trackChanges
set to true.