Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / CSS

Using Knockout.js for SharePoint Web Part Templating: Part 1

4.50/5 (4 votes)
29 Dec 2013CPOL4 min read 26.1K   222  
How to template web parts with Knockout.js framework

Introduction

This topic came up when we got a request to create generic list and library web parts, that would display few common fields like ID, Title, Description, File Url etc. Prior to this request we solved similar issues with OOB list and library web parts with custom XSLT, by creating Visual Studio web part for branding purposes only, or by using Imtech content query web part( which is XSLT solution by design).

At the end, clients hated XSLT solutions and we hated to create new web part for every new list or library. That's where Knockout popped. Why don’t we use Knockout for templates instead XSLT.

I’ll assume that whoever reads this article knows about creating a web part for SharePoint, SharePoint module, java script and html and I will not go into details.

Background

A bit about Knockout

From Knockout web site: “Knockout is a JavaScript library that helps you to create rich, responsive display and editor user interfaces with a clean underlying data model. “

From Wikipedia:

Knockout is a standalone JavaScript implementation of the Model-View-ViewModel pattern with templates. The underlying principles are therefore:

  • a clear separation between domain data, view components and data to be displayed
  • the presence of a clearly defined layer of specialized code to manage the relationships between the view components

Knockout includes the following features:

  • Declarative bindings
  • Automatic UI refresh (when the data model's state changes, the UI updates automatically)
  • Dependency tracking
  • Templating (using a native template engine although other templating engines can be used, such as jquery.tmpl)

So what’s the deal?

First you have your view model:

JavaScript
 var myViewModel = {
     personName: 'Bob',
     personAge: 123
};  

  Then you have a view: 

HTML
The name is <span data-bind="text:personName"></span>

At the end just bind your view to model

JavaScript
 ko.applyBindings(myViewModel); 

We'll talk about model later.

Using the code

Proof of concept

I've created an html mock of our web part. This is useful, because we can prepare java scripts, css files, models and views in advance and test it without SharePoint and visual studio.

You can download proof of concept as separate download from the link above.

References

There would be only two file references. 

One is knockout library itself 

HTML
<script type='text/javascript' src="http://knockoutjs.com/downloads/knockout-3.0.0.js"></script>  

and the other is css file I’ve added to this project

HTML
<link href="css/controls.css" rel="stylesheet" type="text/css" /> 

Model 

I've designed model as Item class. Here it is: 

JavaScript
// Item class definition
var Item = function (id, title, datecreated,url,description,thumbnail) {
   this.id = id;
   this.title = title;
   this.datecreated = datecreated;
   this.url=url;
   this.description=description;
   this.thumbnail=thumbnail;
} 

It’s called item and it has 6 properties:

  1. id - ID of the item
  2. title - Title of the item
  3. datecreated - Creation date of the item
  4. url - Url of the item
  5. description - Description of the item
  6. thumbnail - Thumbnail of the item

View model

Here is the view model

JavaScript
function viewModel1 (){
    var self = this;
    self.items =  [  
     new Item(2, 'News1 title','21.10.2013','javascript:OpenDialog(2);'
               ,'Description News 1','img/pic1.jpg'), 
    new Item(1, 'News 2 title','21.02.2013','javascript:OpenDialog(1);',
               'Description News 2','img/pic2.jpg')
}  

View model has property items, which in fact is collection of Item objects. For mocking purposes we’ve added two Item objects in this collection (News 1 and News 2);

View

Here is the view:
HTML
<div class="glwp glwp-central" id="k1">
  <div class="glwpLine"></div>
  <h5><img src="PublishingImages/siteIcon.png" 
          width="28" height="28" align="absmiddle" />
      News</h5>
  <div class="glwpLineGrey"></div>
    <ul data-bind="foreach:items">
      <li>
       <div class="glwpDate"><span data-bind="text: datecreated" ></span>
       <img class="glwpImage" data-bind="attr: { src: thumbnail }" />         
       </div>
       <div class="glwpText glwpText-central" >
        <a data-bind="attr: { href: url, title: title }" style="min-height:70px;">
         <span class="glwpTextTTL" data-bind="text:title"></span><br />
         <span data-bind="text: description"></span>
        </a>
       </div>
       <div class="glwpSep"></div>
      </li>
    </ul>
</div>  

What we have here:

     It’s pretty simple. We have unordered list bound to our model. One <li> element would be created for every item of our items collection (data-bind="foreach: items”). 

Property binding: 

  •  <span data-bind="text: datecreated"
    ></span>
    - This is the simplest data binding. It would write datecreated property of Item object to text of span element (like: <span>11/11/2013</span>)
  • <img class="glwpImage"
    data-bind="attr: { src: thumbnail }" />
    . This is a bit more complicated binding. It would take thumbnail property of item object and write it to src attribute of img element.
  • <a data-bind="attr: { href: url, title:
    title }" style="min-height:70px;">
    . It would take url property and write it as href attribute of the a element, and title property as title attribute.
  • <span class="glwpTextTTL"
    data-bind="text:title"></span>
    . Title property would be written as text of span element 
  • <span
    data-bind="text: description"></span>
    . Description property would be written as text of span element

So anyone with little knowledge of html and css can customize this template anyway (s)he likes, as long as (s)he provides required properties. 

Binding

JavaScript
ko.applyBindings(viewModel1,document.getElementById('k1'));

Note second parameter in applyBindings method. It says document.getElementById('k1'). Same id is on the first div in our view (<div class="glwp glwp-central" id="k1">). This is helpful if you want to have more than one view model in one page. It tells knockout to bind this specific model (viewModel1) to specific template on our page (k1).

What we have from this? We are going to create web part from this code and one of the web part features is that you can put same web part several times on the same page. So it would be possible to put one web part in SharePoint page to display news and one web part to display projects or documents. And they will coexist together.

If you look at the source you will notice that we have 2 view models (viewModel1 and viewModel2) and two templates (k1 and k2), and two bindings of course. One binding is for news (with images and description) and one binding is for files (no images, and no descriptions). Templates are slightly different.

Final result

Here is the final result 

Image 1

What next? 

You can download (Download ProofOfConcept.zip) ProofOfConcept.zip play a little with it and then move to Part 2 of this series.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)