Knockout.js is an amazing javascript library for binding data and generating html at run time. It uses MVVM pattern that is Model-View-ViewModel pattern. This post assumes that you have a basic understanding of knockout and sharepoint client side object model. If not, then go through the amazing set of tutorials present in knockout (KO) site.
I was recently introduced to KO and found it amazing. But I didn’t find much on how to implement it in sharepoint context. So, I decided to look into it and share with you all my learnings of KO with sharepoint. This post is dedicated to just displaying data from a list in a page using KO. Further posts will focus on adding and removing data too. At the end, we will see if KO is actually a good option for sharepoint or not. The post in the series will be:
- Part I – Displaying Data from SP list. (this one)
- Part II – Adding Data to SP list.
- Part III – Removing Data from SP list.
To start I am using sharepoint 2013 app model. A sharepoint hosted app is created for displaying list’s data in html page present in app context. The structure of the list is:
This is a simple list which contains names of country and their states. Using KO we will display this in a table structure. KO makes the client side code simple and easier to use. HTML, CSS and JS all files are separate and manageable.
So the code for displaying this data is :
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.tableStyle { | |
border-collapse:collapse; | |
border: 1px solid black; | |
text-align:center; | |
width:50%; | |
padding:15px; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
var hostWebUrl; | |
var appWebUrl; | |
var listItems | |
var completeCountryList; | |
$(document).ready(function () { | |
//get the url of app web and host web | |
hostWebUrl = QS("SPHostUrl"); | |
appWebUrl = QS("SPAppWebUrl"); | |
LoadData(); | |
}); | |
//class for saving the countries and their states | |
function CountryList(countryName, stateName) { | |
var self = this; | |
self.CountryName = countryName; | |
self.StateName = stateName; | |
} | |
//View Model to combine data from list into the format which view expects | |
function CountryListViewModel() { | |
var self = this; | |
self.Countries = ko.observableArray([]); | |
self.AddCountries = function (countryName, stateName) { | |
self.Countries.push(new CountryList(countryName, stateName)); | |
} | |
} | |
//function which apply KO bindings and make a call to SP using CSOM | |
function LoadData() { | |
completeCountryList = new CountryListViewModel(); | |
GetList(); | |
ko.applyBindings(completeCountryList); | |
} | |
function GetList() { | |
var context = new SP.ClientContext(appWebUrl); | |
//No need to use SP.RequestExecutor.js for cross domain calls to host web in SP Hosted web | |
/* var factory = new SP.ProxyWebRequestExecutorFactory(appWebUrl); | |
context.set_webRequestExecutorFactory(factory); */ | |
var hostContext = new SP.AppContextSite(context, hostWebUrl); | |
var list = hostContext.get_web().get_lists().getByTitle("KnockoutList"); | |
var camlQuery = new SP.CamlQuery(); | |
camlQuery.set_viewXml("<View><RowLimit>10</RowLimit></View>"); | |
listItems = list.getItems(camlQuery); | |
context.load(listItems, "Include(Id, CountryName, StateName)"); | |
context.executeQueryAsync(ListItemsLoaded, ListItemsFailed); | |
} | |
function ListItemsLoaded(sender, args) { | |
var enumerator = listItems.getEnumerator(); | |
while (enumerator.moveNext()) { | |
var currentItem = enumerator.get_current(); | |
completeCountryList.AddCountries(currentItem.get_item("CountryName"), currentItem.get_item("StateName")); | |
} | |
} | |
function ListItemsFailed(sender, args) { | |
alert(args.get_message()); | |
} | |
function QS(name) { | |
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]"); | |
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"), | |
results = regex.exec(location.search); | |
return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " ")); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<asp:Content ContentPlaceHolderID="PlaceHolderMain" runat="server"> | |
<div id="divCountryList"> | |
<h2>Country List</h2> | |
<br /> | |
<table id="tblCountryList" border="1" class="tableStyle"> | |
<thead> | |
<tr> | |
<th>Country</th> | |
<th>State</th> | |
</tr> | |
</thead> | |
<!– Iterating through every list item using foreach of KO –> | |
<tbody data-bind="foreach: Countries"> | |
<tr> | |
<td data-bind="text: CountryName"></td> | |
<td data-bind="text: StateName"></td> | |
</tr> | |
</tbody> | |
</table> | |
</div> | |
</asp:Content> |
The output page will look like:
This is how we use KO in sharepoint. Notice the object oriented structure of “App.js”. The code is relatively very clean and easy to understand. In next post we will add items in a list using KO. Hope this helps.
excellent post Garima
Thanks Sanju.
This blog helped me to start with KO, Thanks
Glad it helped 🙂
Hi Garima!
This blog help me alot. Being new to SharePoint development, I am wondering if it is possible to get data from two or more sharepoint lists and display via sharepoint hosted app (trying to take advantage of ID), using JS knockout and caml query but still no success. I am working on a school project where i want to use SP list (that i developed via VisualStudio )like SQL database list or simply as data base and trying to display some info using SharePoint Apps in a single table.
Hi Irfan, Using CAML query JOINS you can fetch data from multiple list, but I am not sure whether it will work from client side or not. I have done it in server object model. I am attaching some links, which might be helpful to you. Please go through them once.
List Joins and Projections
SharePoint 2010 CAML List Joins
Lists Join in CAML
Hi. This is a great post, but the list doesn’t work for me. Can you please explain the following:
1. which script libraries did you reference?
2. can you please breakdown where you put each of the scripts (all in a single ‘script editor’? in 3 separate content editors?)
3. Can you please break this process down step by step for the beginners?
thank you a lot
Hi Jack, please find the response below:
1. We need to refer only KO library as jquery is already referred by O365. If you are using other version of SP, then please refer jquery too.
2. you can either put everything in single content editor web part or create different files like app.css, app.js and refer them in the script editor with html. For more details on how to use content editor web part you can refer the following link http://www.nothingbutsharepoint.com/2011/05/09/adding-script-into-a-content-editor-web-part-cewp-in-sharepoint-2010-aspx/
I hope this helps. !!
Thanks for the quick reply — still confused on which library I should be referencing for the entire thing.
/SiteAssets/app.js
/SiteAssets/knockout-3.1.0.js
/SiteAssets/ko.sp-1.0.min.js
I have downloaded you js and css files and I am referencing them from my libraries.
I I now emulate your list exactly and take your script exactly, will this work?
thank you again i really want to get started on this.
Hi Jack, Yes please refer the scripts in following order:
1. jquery
2. knockout-3.1.0.js
3. app.js
Also refer app.css for styling. It should work.
Thank you — the script worked great!
The only setback was the date field on my script isn’t populating in knockout.
field name: ArticleDate
bind=”spDate:ArticleDate” <—this doesn't work
I have been trying to figure it out and I have no idea why.
Reblogged this on sharepointswe.
Sorry i couldn’d understand
10 hostWebUrl = QS(“SPHostUrl”);
11 appWebUrl = QS(“SPAppWebUrl”);
Can you show examle of SPHostUrl and SPAppWebUrl
Hi, So I used this example in a SP hosted app where you get SPHostUrl and SPAppWebUrl in query string (as parameters). I needed them to create SP context. If you are not using SP hosted app then you can safely skip this step. And if you are using app, you will get them in query string. Hope this helps.
Not Work’s 😦
It would be great if you can provide more details like are you using SP hosted app? Can you see QS parameters in the url?