Introducing KoSp – Knockout binding handlers for SharePoint 2013 and 2010 Rest API and SPServices

Ashok Raja
 
Solutions Architect
September 10, 2013
 
Rate this article
 
Views
431

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

IndexLabel NameField TypeRemarks
0KeywordsChoiceMulti- Select
1Sample ContentAttachmentsMulti – Items
2TechnologyLookupMulti-select
3AuthorsPeople/GroupMulti-Select
4Release DateDate TimeFormatted Text
5LevelLookupSingle Selection
6Download BookHyperlinkURL link
7AvailabilityChoiceSingle Selection
8Price – Original PriceCurrencyWith Decimal Value
8Price- DiscountNumberWith Decimal Value
8Price- Discounted PriceCalculated FieldPrice – Discount
9Is ActiveYes / NoFormatted Text
 Last updated onDate TimeFormatted Text
 Last Updated ByPeople/GroupSingle User
 (Book Image)HyperlinkURL of an Image
 (Title)Single Line of textDefault text binding
 (Description)Rich TextDefault html binding

 

KoSp binding for the above screenshot based on REST API

Label NameKoSP binding for REST API
Keywordsdata-bind=”spChoice:Keywords,multi:true”
Sample Contentdata-bind=”spUrl:Attachments,multi:true, dataFormat:’ <br/>'”
Technologydata-bind=”spLookup:Technology,multi:true,dataFormat:’ <br/>'”
Authorsdata-bind=”spUser:Authors,multi:true,dataFormat:’ <br/>'”
Release Datedata-bind=”spDate:ReleaseDate”
Leveldata-bind=”spLookup:Level”
Download Bookdata-bind=”spHref:DownloadURL,displayText:’Download Book'”
Availabilitydata-bind=”spChoice:Availability”
Price – Original Pricedata-bind=”spNumber:Price,dataFormat:’$ 0,0.00′”
Price- Discountdata-bind=”spNumber:DiscountPercentage,dataFormat:’0 %’,defaultValue:’N.A'”
Price- Discounted Pricedata-bind=”spNumber:SellingPrice,dataFormat:’$ 0,0.00′”
Is Activedata-bind=”spBool:IsActive”
Last updated ondata-bind=”spDate:Modified,dataFormat:’DD-MMM-YYYY, hh:mm:ss a'”
Last Updated Bydata-bind=”spUser:ModifiedBy”
Book Imagedata-bind=”spSrc:CoverPhoto”
Titledata-bind=”text:Title”
Descriptiondata-bind=”html:AboutTheBook”

 

KoSp binding for the above screenshot based on SP Services

Label NameKoSP binding for data via SP Services
Keywordsdata-bind=”spChoice:Keywords,src:’sps'”
Sample Contentdata-bind=”spUrl:Attachments,src:’sps’, dataFormat:’ <br/>'”
Technologydata-bind=”spLookup:Technology,,src:’sps’,dataFormat:’ <br/>'”
Authorsdata-bind=”spUser:Authors,src:’sps’,dataFormat:’ <br/>'”
Release Datedata-bind=”spDate:ReleaseDate,src:’sps'”
Leveldata-bind=”spLookup:Level,src:’sps'”
Download Bookdata-bind=”spHref:DownloadURL,displayText:’Download Book'”
Availabilitydata-bind=”spChoice:Availability,src:’sps'”
Price – Original Pricedata-bind=”spNumber:Price,src:’sps’,dataFormat:’$ 0,0.00′”
Price- Discountdata-bind=”spNumber:DiscountPercentage,src:’sps’,dataFormat:’0 %’,defaultValue:’N.A'”
Price- Discounted Pricedata-bind=”spNumber:SellingPrice,src:’sps’,dataFormat:’$ 0,0.00′”
Is Activedata-bind=”spBool:IsActive,src:’sps'”
Last updated ondata-bind=”spDate:Modified,src:’sps’,dataFormat:’DD-MMM-YYYY, hh:mm:ss a'”
Last Updated Bydata-bind=”spUser:ModifiedBy,src:’sps'”
Book Imagedata-bind=”spSrc:CoverPhoto”
Titledata-bind=”text:Title”
Descriptiondata-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.NoArticle
1Introducing KoSpJs – Knockout binding handlers for SharePoint REST API and SPServices – This Article
2Beginning SharePoint development with KoSpJs, REST API and SP Services
3SharePoint Lookup fields, Choice Fields and it’s multi select variants in KoSpJs
4Formatting Date, Number Fields in SharePoint REST API and SPServices with KoSpJs
5Binding Hyperlink and Image URLs with KoSpJs in SharePoint REST API and SPServices
6Retrieving and binding User and User Group Details in SharePoint REST API with KoSpJs

Download Knockout For SharePoint

Author Info

Ashok Raja
 
Solutions Architect
 
Rate this article
 
I am Ashok Raja, Share Point Consultant and Architect based out of Chennai, India. ...read more
 

Leave a comment