This project is read-only.
KnockoutSP is a JavaScript library that will generate a Knockout ViewModel for lists in a SharePoint site. The ViewModel you create with KnockoutSP supports basic CRUD operations on the lists/libraries included in the ViewModel .

To use the library you must add references to knockout, ,datajs, and KnockoutSP (perhaps in the AdditionalPageHead).

You then add another JavaScript file that defines what lists/libraries you want in your ViewModel. In that JavaScript file you create a new KnockoutSP ViewModel by calling new KnockoutSP () passing in the URL of the site you want to generate the ViewModel for:

vm = new KnockoutSP(".."); //url of site to bind to

In this example the JavaScript file containing the code is in a library within a site, so ".." represents the url to the site the library is in.

In your script after you create the ViewModel(named vm in this case)), call vm.loadmetadata.


This pulls the metadata for the site using a datajs call to../listdata.svc/metadata. Having this information allows KnockoutSP to know what list a lookup column points to, what the valid columns in each list are, etc.

After you call vm.loadmetadata() you then call vm.addList for each list you want in your ViewModel. The addList method takes a listDef object as a parameter. The listDef object has a listName property that states the name of the list you want in your ViewModel and a 'columns' property that is an array of objects with one entry for each column from the list you want include in your ViewModel:
"listName": "Company",
"columns": [
{ "colName": "Id" }
,{ "colName": "Title" }
,{ "colName": "Modified" }

One key part of KnockoutSP that it allows you to easily use lookup columns in your vie. Lookup columns can be added to the ViewModel by adding a 'column' property that specifies the lookup Column Name (colName), the type of 'lookupEx' and the 'idColumn associated with the lookup.:
"listName": "Costcenter",
"columns": [
{ "colName": "Id" }
, { "colName": "Title" }
, { "colName": "Company", "type": "lookupEx", "idColumn": "CompanyId" }

;In the example above the CostCenter list has a lookup column on the Company list. The rest data service exposes the ID of the company as CompanyId, so that needs to be specified in the idColumn.

After calling addList for all the lists you want in your model, call the load method on your viewModel.
This will cause knockoutSP to retrive the data for the specified lists and columns from SharePoint.

You may be able to bind to your model at this point in your code (after vm.load()) under some circumstances(if there are no lookup columns), but you may need to wait for all the data to be loaded before binding with this code:
vm.allDataLoadedFunc().done(function () {

The allDataLoaded is a JavaScript deferred object that resolves once all the lists have been loaded, so if you place your ko.applyBindings here, it won't be called until the actual data from all of the lists you requested has been retrieved and placed in your ViewModel..

The ViewModel created by KnockoutSP exposes a 'notifier' knockout subscribable that your code can use to be notified when items have been added, changed, or deleted in the list/library in the viewModel:
vm.CostCenterNotifier.subscribe(function (spListItem) {
SP.UI.Notify.addNotification(spListItem.Title() + " deleted");
}, vm, "deleted");

In the above example I'm subscribing to the CostcenterNotifier's deleted event and displaying a SharePoint notification when an item has been deleted (the Notifier events pass in the object added, deleted or modified as a parameter).

The sourceCode for the example described above can be found in the test2.js file of this project.

Once the ViewModel is created standard Knockout code can be used to manipulate it. The test2.html file of this project show an example.

For lookup columns all the values of the referenced items are available when binding to the item with the lookup column:

<span data-bind="text:CostCenter().Company().Title"></span>

In this example i bound to a 'Budget list that has a lookup column on the costcenter list, which in turn has a lookup column on the Company list. The example displays the Title of the Company of the Costcenter for the given Budget (if present).

Deleting and Updating items are done by binding to methods on the root of the viewModel:

<input type="button" data-bind="click: $root.deleteItem" value="Delete" />
<input type="button" data-bind="click: $root.saveItem" value="save" />

lookup columns can be bound to dropdowns that display items from the source list like this:
<select data-bind="options:$root.Costcenter,optionsCaption:'cost center', optionsText:'Title', optionsValue:'Id', value:CostCenterId "></select>

(there is curently no sppurt for multi-select lookups)

To Add Items, you bind to a 'newXXX' object in the vm (where XXX is the name of the list) perhaps in a table header:
<tr data-bind="with:newBudgetLine">
<th> <input type="text" data-bind="value:Title"></input></th>
<th> <input type="text" data-bind="value:Amount"></input></th>
<th><select data-bind="options:$root.Account,optionsCaption:'select Account', optionsText:'Title', optionsValue:'Id', value:AccountId "></select></th>
<th> <input type="button" data-bind="click: add" value="save" /></th>


The update is performed by binding a button (or something) to the 'add' event of the 'newXXX' object.

I'm working on adding support for Multi-select lookup fields and reverse-Lookup columns(.

Further information will be available at

Last edited Sep 14, 2013 at 10:09 PM by russgove, version 9


No comments yet.