Ashok Raja's Blog
Introducing KoSp - Knockout binding handlers for SharePoint 2013 and 2010 Rest API and SPServices
by Ashok Raja T 10. September 2013 23:08

Today I have released KoSp (Knockout for SharePoint) in codeplex. If you love client side scripting in SharePoint 2013 or SharePoint 2010 with Rest API or SP services, then this is for you. KoSp provides a set of knockout binding handlers for SharePoint list data that can be bound directly to client side html controls like any other default knockout binder.

Json data from SharePoint Rest API via oData queries or data from SPservices based on CAML queries could be quiet complex depending on the data type of SharePoint list columns. Some of the complex SharePoint Field Types like lookups, choices, users and multi-select variants of these columns are represented as nested json objects which also requires further parsing of data depending on the data type of the respective SharePoint field. KoSp leverages the binding capabilities of knockout by providing additional custom knockout binding handlers specifically targeted towards json data from SharePoint lists.

Date Time parsing and Number formatting is one of the key challenges that every one encounters while handling json data. KoSp uses moment js and numeral js to handle parsing and formatting of dates and numbers instead of re-inventing the wheel .

KoSp is released in 2 variants in Code Plex. One is the usual minified version ( ko.sp-[Version Number].min.js) and the other is a minified version with embedded minified version of moment.js and numerals.js (ko.sp-[Version Number].min.Ex.js) . If you have already referred Moment Js and Numeral Js in your SharePoint page , then use ko.sp-[Version Number].min.js variant instead of ko.sp-[Version Number].min.Ex.js

Pre-requisites

The below JavaScript libraries are pre-requisites for KoSp

1. Knockout Js ( Tested with Version 2.3 and 3.0 Beta)

2. jQuery ( For REST API calls )

3. Moment JS  ( For Date Time parsing and formatting, bundled with ko.sp-[Version Number].min.Ex.js)

4. Numerals JS ( For Number formatting, bundled with ko.sp-[Version Number].min.Ex.js)

5. SP Services – Optional, its required only if you wish to perform data requests via lists.asmx with CAML queries instead of oData queries with REST API

 

Project Home in codeplex  http://kosp.codeplex.com

The below is the screen shot of SharePoint list data bound to client side html controls with knockout and KoSp.

Kosp and Rest API

This list contains all the data types supported by SharePoint Rest API. The below screenshot shows the field names and their data types.

clip_image003

Default View properties screen of a record

clip_image004

SharePoint Field Types and its representation

clip_image006

Index Label Name Field Type Remarks
0 Keywords Choice Multi- Select
1 Sample Content Attachments Multi – Items
2 Technology Lookup Multi-select
3 Authors People/Group Multi-Select
4 Release Date Date Time Formatted Text
5 Level Lookup Single Selection
6 Download Book Hyperlink URL link
7 Availability Choice Single Selection
8 Price – Original Price Currency With Decimal Value
8 Price- Discount Number With Decimal Value
8 Price- Discounted Price Calculated Field Price - Discount
9 Is Active Yes / No Formatted Text
  Last updated on Date Time Formatted Text
  Last Updated By People/Group Single User
  (Book Image) Hyperlink URL of an Image
  (Title) Single Line of text Default text binding
  (Description) Rich Text Default html binding

 

KoSp binding for the above screenshot based on REST API

Label Name KoSP binding for REST API
Keywords data-bind="spChoice:Keywords,multi:true"
Sample Content data-bind="spUrl:Attachments,multi:true, dataFormat:' <br/>'"
Technology data-bind="spLookup:Technology,multi:true,dataFormat:' <br/>'"
Authors data-bind="spUser:Authors,multi:true,dataFormat:' <br/>'"
Release Date data-bind="spDate:ReleaseDate"
Level data-bind="spLookup:Level"
Download Book data-bind="spHref:DownloadURL,displayText:'Download Book'"
Availability data-bind="spChoice:Availability"
Price – Original Price data-bind="spNumber:Price,dataFormat:'$ 0,0.00'"
Price- Discount data-bind="spNumber:DiscountPercentage,dataFormat:'0 %',defaultValue:'N.A'"
Price- Discounted Price data-bind="spNumber:SellingPrice,dataFormat:'$ 0,0.00'"
Is Active data-bind="spBool:IsActive"
Last updated on data-bind="spDate:Modified,dataFormat:'DD-MMM-YYYY, hh:mm:ss a'"
Last Updated By data-bind="spUser:ModifiedBy"
Book Image data-bind="spSrc:CoverPhoto"
Title data-bind="text:Title"
Description data-bind="html:AboutTheBook"

 

KoSp binding for the above screenshot based on SP Services

Label Name KoSP binding for data via SP Services
Keywords data-bind="spChoice:Keywords,src:'sps'"
Sample Content data-bind="spUrl:Attachments,src:'sps', dataFormat:' <br/>'"
Technology data-bind="spLookup:Technology,,src:'sps',dataFormat:' <br/>'"
Authors data-bind="spUser:Authors,src:'sps',dataFormat:' <br/>'"
Release Date data-bind="spDate:ReleaseDate,src:'sps'"
Level data-bind="spLookup:Level,src:'sps'"
Download Book data-bind="spHref:DownloadURL,displayText:'Download Book'"
Availability data-bind="spChoice:Availability,src:'sps'"
Price – Original Price data-bind="spNumber:Price,src:'sps',dataFormat:'$ 0,0.00'"
Price- Discount data-bind="spNumber:DiscountPercentage,src:'sps',dataFormat:'0 %',defaultValue:'N.A'"
Price- Discounted Price data-bind="spNumber:SellingPrice,src:'sps',dataFormat:'$ 0,0.00'"
Is Active data-bind="spBool:IsActive,src:'sps'"
Last updated on data-bind="spDate:Modified,src:'sps',dataFormat:'DD-MMM-YYYY, hh:mm:ss a'"
Last Updated By data-bind="spUser:ModifiedBy,src:'sps'"
Book Image data-bind="spSrc:CoverPhoto"
Title data-bind="text:Title"
Description data-bind="html:AboutTheBook"

 

Knockout View and View Modal based on Rest API

 <script src="js/jquery-1.8.3.min.js"></script>
 <script src="js/knockout-3.0.0beta.js"></script>
 <script src="js/ko.sp-1.0.min.Ex.js"></script>
 <link href="css/books.css" rel="stylesheet" />
 
 <div data-bind="template: { name: 'allBooks-template', foreach: Books }"></div>
 
 <script type="text/html" id="allBooks-template">
     <div class="bookItem">
         <div class="bookImg">
             <img width="200px" height="110px" data-bind="spSrc:CoverPhoto" />
         </div>
         <div class="bookContent">
             <div class="bookTitle" data-bind="text:Title"></div>
             <div class="bookDesc" data-bind="html:AboutTheBook"></div>
             <span><b>Keywords</b></span>
             <div data-bind="spChoice:Keywords,multi:true"></div>
             <span><b>Sample Content</b></span>
             <div data-bind="spUrl:Attachments,multi:true, dataFormat:'<br/>'"></div>
 
         </div>
         <div class="bookDetails">
             <div>
                 <div><b>Technology</b></div>
                 <span data-bind="spLookup:Technology,multi:true,dataFormat:'<br/>'"></span>
             </div>
             <div>
                 <div><b>Author(s)</b></div>
                 <span data-bind="spUser:Authors,multi:true,dataFormat:'<br/>'"></span>
             </div>
             <div>
                 <div><b>Release Date</b></div>
                 <span data-bind="spDate:ReleaseDate"></span>
             </div>
             <div>
                 <div><b>Level</b></div>
                 <span data-bind="spLookup:Level"></span>
             </div>
             <div>
                 <a href="#" data-bind="spHref:DownloadURL,displayText:'Download Book'"></a>
             </div>
         </div>
         <div class="bookDetails">
             <div>
                 <div><b>Availability</b></div>
                 <span data-bind="spChoice:Availability"></span>
             </div>
             <div>
                 <div><b>Price</b></div>
                 Original Price <b><span data-bind="spNumber:Price,dataFormat:'$ 0,0.00'"></span></b>
                 <br />
                 Discount <b><span data-bind="spNumber:DiscountPercentage,dataFormat:'0 %',defaultValue:'N.A'"></span></b>
                 <br />
                 Discounted Price <b><span data-bind="spNumber:SellingPrice,dataFormat:'$ 0,0.00'"></span></b>
             </div>
             <div>
                 <div><b>Last updated on</b></div>
                 <span data-bind="spDate:Modified,dataFormat:'DD-MMM-YYYY, hh:mm:ss a'"></span>
             </div>
             <div>
                 <div><b>Last updated By</b></div>
                 <span data-bind="spUser:ModifiedBy"></span>
             </div>
             <div>
                 <div><b>Is Active</b></div>
                 <span data-bind="spBool:IsActive"></span>
             </div>
         </div>
         <div style="clear: both"></div>
     </div>
 </script>
 <script type="text/javascript">
     function BookModal() {
         var self = this;
         self.Books = ko.observableArray([]);
         $.getJSON(_spPageContextInfo.webAbsoluteUrl + "/_vti_bin/listdata.svc/Books?$expand=Level,Technology,Keywords,Availability,Authors,Attachments,ModifiedBy&$select=Title,Level/Title,Technology/Title,AboutTheBook,Keywords/Value,CoverPhoto,Attachments,Authors/Name,ReleaseDate,DownloadURL,Availability,Price,DiscountPercentage,SellingPrice,Modified,ModifiedBy/Name,IsActive",
             function (data) {
                 if (data.d.results) {
                     self.Books(ko.toJS(data.d.results));
                 }
             }
         );
     }
     ko.applyBindings(new BookModal());
 </script>

Knockout View and View Modal based on SP Services

 <script src="js/jquery-1.8.3.min.js"></script>
 <script src="js/jquery.SPServices-2013.01.min.js"></script>
 <script src="js/knockout-3.0.0beta.js"></script>
 <script src="js/ko.sp-1.0.min.Ex.js"></script>
 <link href="css/books.css" rel="stylesheet" />
 
 <div data-bind="template: { name: 'allBooks-template', foreach: Books }"></div>
 
 <script type="text/html" id="allBooks-template">
 	<div class="bookItem">
 		<div class="bookImg">
 			<img width="200px" height="110px" data-bind="spSrc:CoverPhoto" />
 		</div>
 		<div class="bookContent">
 			<div class="bookTitle" data-bind="text:Title"></div>
 			<div class="bookDesc" data-bind="html:AboutTheBook"></div>
 			<span><b>Keywords</b></span>
 			<div data-bind="spChoice:Keywords,src:'sps'"></div>
 			<span><b>Sample Content</b></span>
 			<div data-bind="spUrl:Attachments,src:'sps'"></div>
 		</div>
 		<div class="bookDetails">
 			<div>
 				<div><b>Technology</b></div>
 				<span data-bind="spLookup:Technology,src:'sps',dataFormat:'<br/>'"></span>
 			</div>
 			<div>
 				<div><b>Author(s)</b></div>
 				<span data-bind="spUser:Authors,src:'sps',dataFormat:'<br/>'"></span>
 			</div>
 			<div>
 				<div><b>Release Date</b></div>
 				<span data-bind="spDate:ReleaseDate,src:'sps'"></span>
 			</div>
 			<div>
 				<div><b>Level</b></div>
 				<span data-bind="spLookup:Level,src:'sps'"></span>
 			</div>
 			<div>
 				<a href="#" data-bind="spHref:DownloadURL,displayText:'Download Book'"></a>
 			</div>
 		</div>
 		<div class="bookDetails">
 			<div>
 				<div><b>Availability</b></div>
 				<span data-bind="spChoice:Availability,src:'sps'"></span>
 			</div>
 			<div>
 				<div><b>Price</b></div>
 				Original Price <b><span data-bind="spNumber:Price,src:'sps',dataFormat:'$ 0,0.00'"></span></b>
 				<br />
 				Discount <b><span data-bind="spNumber:DiscountPercentage,src:'sps',dataFormat:'0 %',defaultValue:'N.A'"></span></b>
 				<br />
 				Discounted Price <b><span data-bind="spNumber:SellingPrice,src:'sps',dataFormat:'$ 0,0.00'"></span></b>
 			</div>
 			<div>
 				<div><b>Last updated on</b></div>
 				<span data-bind="spDate:Modified,src:'sps',dataFormat:'DD-MMM-YYYY, hh:mm:ss a'"></span>
 			</div>
 			   <div>
 				<div><b>Last updated By</b></div>
 				<span data-bind="spUser:ModifiedBy,src:'sps'"></span>
 			</div>
 			<div>
 				<div><b>Is Active</b></div>
 				<span data-bind="spBool:IsActive,src:'sps'"></span>
 			</div>
 		</div>
 		<div style="clear: both"></div>
 	</div>
 </script>
 <script type="text/javascript">
 	function Book(data) {
 		this.Title = ko.observable(data.Title);
 		this.Level = ko.observable(data.Level);
 		this.Technology = ko.observable(data.Technology);
 		this.AboutTheBook = ko.observable(data.AboutTheBook);
 		this.Keywords = ko.observable(data.Keywords);
 		this.Availability = ko.observable(data.Availability);
 		this.ReleaseDate = ko.observable(data.ReleaseDate);
 		this.Price = ko.observable(data.Price);
 		this.DiscountPercentage = ko.observable(data.DiscountPercentage);
 		this.SellingPrice = ko.observable(data.SellingPrice);
 		this.CoverPhoto = ko.observable(data.CoverPhoto);
 		this.DownloadURL = ko.observable(data.DownloadURL);
 		this.AvailableQuantity = ko.observable(data.AvailableQuantity);
 		this.Authors = ko.observable(data.Authors);
 		this.IsActive = ko.observable(data.IsActive);
 		this.Modified = ko.observable(data.Modified);
 		this.ModifiedBy = ko.observable(data.ModifiedBy);
 		this.Attachments = ko.observable(data.Attachments);
 	}
 	function BooksModal() {
 		var self = this;
 		self.Books = ko.observableArray([]);
 		$().SPServices({
 			operation: "GetListItems",
 			async: false,
 			listName: "Books",
 			CAMLQueryOptions: "<QueryOptions><IncludeAttachmentUrls>True</IncludeAttachmentUrls></QueryOptions>",
 			CAMLViewFields: "<ViewFields Properties='True' />",
 			CAMLQuery: "<Query></Query>",
 			completefunc: function (xData, Status) {
 				var spsData = $(xData.responseXML).SPFilterNode("z:row").SPXmlToJson({ includeAllAttrs: true, removeOws: true });
 				if (spsData) {
 					$.each(spsData, function (k, l) {
 						self.Books.push(new Book({
 							Title: l.Title,
 							Level: l.Level,
 							Technology: l.Technology,
 							AboutTheBook: l.About_x0020_The_x0020_Book,
 							Keywords: l.Keywords,
 							Availability: l.Availability,
 							ReleaseDate: l.Release_x0020_Date,
 							Price: l.Price,
 							DiscountPercentage: l.Discount_x0020_Percentage,
 							SellingPrice: l.Selling_x0020_Price,
 							CoverPhoto: l.Cover_x0020_Photo,
 							DownloadURL: l.Download_x0020_URL,
 							AvailableQuantity: l.Available_x0020_Quantity,
 							Authors: l.Authors,
 							IsActive: l.Is_x0020_Active,
 							Modified: l.Modified,
 							ModifiedBy: l.Editor,
 							Attachments: l.Attachments
 						}))
 					});
 				}
 			}
 		});
 	}
 	ko.applyBindings(new BooksModal());
 </script>

Articles on Knockout For SharePoint (KoSp) Series

Sl.No Article
1 Introducing KoSpJs - Knockout binding handlers for SharePoint REST API and SPServices - This Article
2 Beginning SharePoint development with KoSpJs, REST API and SP Services
3 SharePoint Lookup fields, Choice Fields and it's multi select variants in KoSpJs
4 Formatting Date, Number Fields in SharePoint REST API and SPServices with KoSpJs
5 Binding Hyperlink and Image URLs with KoSpJs in SharePoint REST API and SPServices
6 Retrieving and binding User and User Group Details in SharePoint REST API with KoSpJs

Download Knockout For SharePoint

blog comments powered by Disqus