PnP JavaScript Library with Knockout JS in SharePoint

This post contains the sample code used as a starting point to use PnP JS Core component library with Knockout JS framework to show the list of child sites.

From my previous posts, we can learn how to integrate PnP JavaScript library in Angular JS 1.0 and React JS frameworks. Find the links for those posts,

PnP JavaScript with Angular JS 1.0

PnP JavaScript with React JS

In this article, I am taking the same example but different JS framework to build UI interfaces.

In modern SharePoint experience, SharePoint team uses the Knockout JS as one of the framework to update the UI interfaces.

Knockout JS supports MVVM pattern (Model – View – ViewModel) to build web UI interface and it follows different model in updating DOM compared to other JS frameworks. You can learn more about Knockout JS from their site ( https://knockoutjs.com ). They are providing nice examples and tutorials to learn step by step. (I have learned from those tutorials)

PnP-JS-Core library contains the number of extensible methods and properties. By using that we can achieve the various actions in a simple code. To know more about this library component, visit the below links,

Introduction to PnP-JS-Core

Basic SharePoint web operations using PnP-JS-Core

Filtering SharePoint Object Collections using PnP-JS-Core

After reading the above links, which gives you some basic idea about PnP-JS-Core library and how to use that library in accessing the SharePoint.

Now we back on integration part. Before starting we have to identify some required file for this example.

What are the essential files required?

knockoutjs,js A latest knockout java script library for building user interfaces

Pnp.js PnP JavaScript library

Fetch.js Used by PnP js file to handle web requests and responses (Required for IE)

Promise.js Used by PnP js file to handle web requests and responses (Required for IE)

Note: Fetch JS & Promise JS files are required to run PnP methods in some browsers (IE).

In our example, we have to create a sample.html file under Style Library or Site Assets. Here I am creating the file under Site Assets Library.

Include Script Files:

I have uploaded the required script files under Site Assets library, and added the below lines to our sample html file.

[code language=”javascript”]
<script type="text/javascript" src="/siteassets/scripts/pnp.min.js"></script>
<script type="text/javascript" src="/siteassets/scripts/fetch.js"></script>
<script type="text/javascript" src="/siteassets/scripts/promise.min.js"></script>
<script type="text/javascript" src="/siteassets/scripts/knockout-3.4.0.js"></script>
[/code]

Note: I have downloaded the latest knockout js file and referenced in the script.

Include HTML:

Add the below css styles and html snippet to the sample html file.

[code language=”html”]

<!– To style table in html –>
<style type="text/css">
.web-table th{ background-color:#ddd; border:2px solid #fff;}
.web-table td{ background-color:#eee; border:2px solid #fff;}
.web-heading{ padding:2px;}
</style>
<div>
<h2 class="web-heading">Sub Sites</h2>
<div>
<table width="100%" cellpadding="10" cellspacing="2" class="web-table">
<thead>
<tr>
<th>Title</th>
<th>Id</th>
<th>Created</th>
<th>Web Template</th>
</tr>
</thead>
<tbody data-bind="foreach: webSites">
<tr >
<td data-bind="text: Title"></td>
<td data-bind="text: Id"></td>
<td data-bind="text: Created"></td>
<td data-bind="text: WebTemplate"></td>
</tr>
</tbody>
</table>
<p data-bind="visible: webSites().length <= 0">No websites</p>
</div>
</div>

<script type="text/javascript">
<!- – Insert Knockout JS Code – – >
</script>
[/code]

  • data-bind attributes are how Knockout lets you declaratively associate viewmodel properties with DOM elements. You just used the text binding to assign text to your DOM elements.
  • webSites represent observable object – this is a property that automatically will issue notifications whenever their value changes
  • If sub sites are not available, “No websites” content visible to the user by using visible binding by comparing with length property of a observable property.

Include Knockout JS Code:

[code language=”javascript”]

// This is a simple viewmodel – JavaScript that defines the data and behavior of your UI
function websViewModel() {
var self = this;
self.webSites = ko.observableArray();

//Include PnP JS Code to set the subsite collection to self.webSites variable
}

// Activates knockout.js
ko.applyBindings(new websViewModel());

[/code]

ko.applyBindings method activates the knockout code on websViewModel. And the properties and methods are executed and store the variables in a viewModel property.

Include PnP JS Code:

Replace the include PnP JS Code comment from the html snippet with the below PnP code.

[code language=”javascript”]
$pnp.sp.web.webs.get().then(function(result) {
self.webSites(result); //knockout JS Code used to set the result object to websites
});

[/code]

PnP executes the code and set the returned value to webSites observable property. We can use this observable property in html to update the content in UI.

Full Sample Code:

Insert the below code with in Script Editor or Content Editor web-part.

[code language=”javascript”]

<style type="text/css">
.web-table th{ background-color:#ddd; border:2px solid #fff;}
.web-table td{ background-color:#eee; border:2px solid #fff;}
.web-heading{ padding:2px;}
</style>
<script type="text/javascript" src="/siteassets/scripts/fetch.js"></script>
<script type="text/javascript" src="/siteassets/scripts/promise.min.js"></script>
<script type="text/javascript" src="/siteassets/scripts/pnp.min.js"></script>
<script type="text/javascript" src="/siteassets/scripts/knockout-3.4.0.js"></script>

<div>
<h2 class="web-heading">Sub Sites</h2>
<div>
<table width="100%" cellpadding="10" cellspacing="2" class="web-table">
<thead>
<tr>
<th>Title</th>
<th>Id</th>
<th>Created</th>
<th>Web Template</th>
</tr>
</thead>
<tbody data-bind="foreach: webSites">
<tr >
<td data-bind="text: Title"></td>
<td data-bind="text: Id"></td>
<td data-bind="text: Created"></td>
<td data-bind="text: WebTemplate"></td>
</tr>
</tbody>
</table>
<p data-bind="visible: webSites().length <= 0">No websites</p>
</div>
</div>

<script type="text/javascript">
// This is a simple viewmodel (websViewModel) – JavaScript that defines the data and behavior of your UI
function websViewModel() {
var self = this;

self.webSites = ko.observableArray();
$pnp.sp.web.webs.get().then(function(result) {
//knockout JS Code used to set the result object to webSites
self.webSites(result);
});
}
// Activates knockout.js
ko.applyBindings(new websViewModel());
</script>

[/code]

Output:

Shows website using Knockout JS & PnP-JS-Core
Fig 1: Shows website using Knockout JS & PnP-JS-Core

Conclusion:

This article provides a simple example to lists the sub sites in a table format using Knockout JS framework.

Shantha Kumar
Shantha Kumar
Articles: 280