Sharepoint Framework Ui Customization Angular June-2017
Sharepoint Framework Ui Customization Angular June-2017
Framework
With Angular, Webpack and Kendo UI
WHITEPAPER
Table of Contents
Introduction / 4
Validation / 24
PDF Generation / 26
Progress.com 2
Building the App: Behind the Scenes / 33
Typings / 34
Gulp / 35
Webpack Bundling / 39
Getting Started / 46
Summary / 46
Progress.com 3
Introduction Future of
This whitepaper discusses the future of SharePoint SharePoint
development and where Progress® Kendo UI® can
provide value in custom SharePoint application
development.
Development
We want to follow the trails of a SharePoint The future of SharePoint development and
developer, where we’ve been (with Full Trust, customization is the SharePoint Framework.
Sandbox, App/Add-In Web) and where we are
heading next with the open web stack. This was It is a client-side based framework that allows
an inevitable change that was happening with or JavaScript customizations to work on top of
without Microsoft, based on all client projects that SharePoint Online. It will also work with SharePoint
we see and on talking with the community at large. Server on-premises in a future update.
With the upcoming SharePoint Framework ("First If you think SharePoint and Microsoft have been
release this summer"), Microsoft is no longer standing still in the last few years—you might be
dictating our toolset, but embracing open web shocked. They have silently come a very long way!
technologies and wanting to support industry
trends as first class supported customizations within The Framework and Why it’s Awesome
SharePoint.
Firstly, it is a recognition that Microsoft should
There is a lot to catch up on with the SharePoint adopt and build on top of progressive web
Framework so we better get started! technologies. Instead of learning Microsoft’s version
of a technology that’s rapidly outdated, we can
Our main goals for this whitepaper are to: use the latest and greatest in jQuery, KnockoutJS,
AngularJS or ReactJS—even mix and choose
•• Get you excited about the new SharePoint technology based on our needs. These open web
Framework and related web stack technologies. technologies are all supported on SharePoint
Online.
•• Use a great set of web stack tools that work well
together to build a practical SharePoint business We are no longer asked to learn strange object
application that can get you started with these models or peculiar syntaxes like CAML or
technologies today. DisplayTemplates. Instead, we just need the
© 2017 Progress. All Rights Reserved.
Progress.com 4
effective and productive. source on GitHub.
For businesses, this means we can train our developers In addition, Microsoft is releasing a tool called the
in skills that are useful even outside of SharePoint. It is SharePoint Workbench, which will allow us to run
also far easier to hire web developers and have them and test our controls and applications within an
contribute to a SharePoint project quickly. offline environment so we can work on our projects
The Tools
Progress.com 5
and run automated tests when we are not connected All modern browsers are supported as first class.
to SharePoint Online.
And all the new experiences are designed to be
Open Source responsive and rescale accordingly to the UI—
whether it is desktop or mobile, across all platforms.
All these framework, libraries and new tools are
released Open Source. We can now take a copy of This matches very well with developments in the
the code, improve it and create a pull request to web world, with technologies like Cordova allowing
submit back to the community. web applications to run within native applications,
the SharePoint Mobile App was born.
There are also several community projects spinning
up around the official releases, adding capabilities, It promises a smooth interface, caching and seamless
libraries and components available to our toolkit. connection to Office Client Apps, OneDrive and the
Most recently, the release of the PnP-JS-Core library new Team Site experience.
provides a new wrapper around the modern REST
API that should help developers transition into client The Mobile App also had the promise that
side development for the SharePoint Framework. customizations on top of the SharePoint Framework
will run within the Mobile App. This icing on the cake
Not too long ago, SharePoint developers using open may yet prove to be the biggest selling factor to
source libraries like SPServices to build their web businesses. If we come to Microsoft for this ride and
parts and application were somewhat considered develop the "new way," we get the experience across
cowboys. Today, developers are being encouraged all mobile devices—free.
to use them as best practice.
Timeframe
Jeff Teper and the Focus on Modern and
Mobile The SharePoint Framework (SPFx) was in private
preview, and through the writing of this whitepaper
One big exciting development on the roadmap was has gone into developer preview and released to the public.
the return of Jeff Teper, the father of SharePoint,
back to lead SharePoint efforts within Microsoft.
Progress.com 6
Update: Developer Preview (August 2016) run within SharePoint, or even in Office Add-Ins.
The Developer Preview, our first taste and our There are a multitude of scenarios that have taken
feedback to Microsoft, is in two areas. Firstly, us to this point. The next step is to evaluate the
Microsoft’s own guidance doesn’t cover Angular yet. components and technologies that are available to
We believe this to be crucial before public release as us and pick the ones that we will focus on.
a majority of full client-side applications developed in
the last few years are using the Angular framework. Next, we will discuss web technologies that we
believe align well with the direction in the open
Secondly, SPFx build Gulp tasks and Webpack web stack. We present this technology set as a
configurations are hidden from the user. This good solution that works really well, but keep in
hides some of the ‘magic’ but also makes the build mind many more technologies, e.g. KnockoutJS or
process difficult to customize for different teams. For ReactJS will also work fine. You should evaluate this
example, if we want to add more tasks to the build suggested list and make adjustments accordingly,
pipeline, we want to integrate a different testing relating to your team’s situation.
framework or even deploy the solution to existing
SharePoint 2013 On-Premises—the current Gulp Technologies
tasks hides that.
Node, NPM—In the JavaScript world, Node is the
But we are expecting public release to happen very runtime that lets us run code without a browser.
soon this year. And we hope to work with Microsoft The modern web stack runs on JavaScript—script
to address some of these issues. running in Node on the server and script running in
browser on the client.
Selecting Our NPM is like nuget for getting libraries and tools that
we need to run tools as well as libraries for the web
Web Stack and UI application. Historically, Bower was used for client-side
JavaScript libraries—technologies such as Webpack
module bundling means that there is no longer a real
Library distinction between what is a client-side library or
what is just a JavaScript library. If it’s needed on the
client side, the bundler will pack it for us.
Ready, Set, Go! Onward to the SharePoint
Framework AngularJS—Framework that helps us manage
databinding, components and composition. This is
© 2017 Progress. All Rights Reserved.
So, you are all set and excited about the SharePoint one of the most popular web frameworks that likely
Framework. You are looking to customize Office doesn’t need any introduction. Many companies have
365. You want to bring your customizations down to
SharePoint Mobile. You want to build apps that will
Progress.com 7
already invested skills and code to this framework. year and is rapidly gaining momentum. At its core,
its unique philosophy is to utilize parallel code
For this project, we pick Angular over React because splitting to load JavaScript quickly into the browser.
of our own experiences, having used Angular in And it is designed to not only minify and uglify
client projects in the past and the readily available JavaScript, but also able to generate source-maps
UI frameworks like Kendo UI that are optimized for and run a development Webpack server that could
Angular. recompile on the fly. Webpack is fairly opinionated
about how things should work, but has taken over
Yeoman—‘The web’s scaffolding tool for modern much of the functionality that used to depend on
webapps’ is one of the most exciting pieces to the several different tools—Browserify, Gulp and require/
SharePoint Framework puzzle. Before, we were systemjs. In the SharePoint Framework, Webpack will
dependant on Visual Studio Wizards to create the be one of the pieces used to package our resources
new SharePoint project. Now, we can generate the both to run in a local development server, or for
web project using the Yeoman generator running on deployment to a CDN to be used in SharePoint itself.
node.js from the command prompt.
Visual Studio Code—We choose to use Visual
Microsoft currently has an ongoing very successful Studio Code, as it’s a much simpler code editor.
Yeoman template for creating Office Add-ins VS Code doesn’t try to be a fully Integrated
called generator-office (yo office). The SharePoint Development Environment (IDE) with full SDKs and
Framework generator will be called generator- wizards. Instead, it tries to be a good code editor
sharepoint (yo sharepoint). that understands files grouped in folders really well.
Although we are highly anticipating the SharePoint Where does Kendo UI fit in and what are the
template, you won’t be restricted to it. You can make Alternatives?
your own adaptations and templates and share them
within your development team or with the entire If we are building business applications, we are
community. probably building forms and we need great controls
with out-of-the-box validation capabilities. Basic
For our project, we will use the PnP JSCore Yeoman controls like textbox, text area and date pickers are a
Template also released by Microsoft to get started. given. As we consider additional controls like grid view,
rich text editing and multi-lingual support for global
Gulp—Task runner, build, test, deploy to SharePoint.
Traditionally, Gulp takes a more active role in minifying
and concatenating files before deployment. That task
has largely been taken over by Webpack. Gulp remains
© 2017 Progress. All Rights Reserved.
Progress.com 8
customers, using a UI framework is a no brainer. Kendo UI Professional is next step with 70+
advanced controls (grid, spreadsheet, Gantt
A Grasp of What’s Out There and Our and scheduler being our recent favorites). While
Experience with it: Kendo UI Pro isn’t open source, we do get access
to dedicated support and full source code to
•• UI Bootstrap—is well tested and used with review so we can still take a crack at a particular
Angular, but not particularly optimized for problem by reading the source code ourselves.
SharePoint or Office 365. You may have some It’s the best of both worlds.
growing pains as you adjust CSS and loading
orders to get UI Bootstrap to work nicely. Kendo UI controls support jQuery, Angular 1.x and
Bootstrap’s Responsive CSS doesn’t work with Angular.
SharePoint MasterPage out of box, so you will
need to tinker with that. When single page React support is coming soon.
applications (SPAs) are supported properly with
SharePoint Framework, this may change. All these libraries will work with any SharePoint and
Angular projects and you don’t have to use Kendo
•• Office UI Fabric Core, Components and UI. Our example does, but it can be replaced with
ngOfficeUIFabric—Office UI Fabric is a set of ngOfficeUIFabric.
styles and components provided and used by
Microsoft to build their own customizations. There are plenty of things to learn and get going
The focus is Office 365 friendly CSS, and in the new framework—spending time on making a
components designed for plain JavaScript control work is probably less important in the grand
or React. As Microsoft doesn’t provide an scheme of things.
Angular implementation, ngOfficeUIFabric is a
community attempt to create native wrappers for
Office UI Fabric components, but along with the
components themselves they are not yet widely
adopted and you may find support difficult to
come by. UI Fabric Core is mainly supported for
SharePoint Online, Office Add-Ins and latest “I have some first-hand experiences here
versions of SharePoint 2013/2016. [at a client] customizing both UI-Bootstrap
and ngOfficeUIFabric on several client
•• Kendo UI comes in three plans—Core, projects. Halfway through each project I’m
Professional and Complete, where Complete thinking, maybe I should have just gone for
goes beyond the scope of this project as it a commercial supported framework and not
© 2017 Progress. All Rights Reserved.
includes additional libraries such as wrappers spend all this time making controls work.”
for MVC, JSP and PHP. Kendo UI Core is free,
open source and community-supported.
Progress.com 9
Building the App: Contract
Register
We want to demonstrate how the technologies On a functional level, the application should:
discussed in the previous section work together and
build a simple yet useful application: The Contract • Show a list of all contracts and status (the
Register. register)
• Allow for adding, editing and viewing contracts
Use Case • Signed contracts should be uploaded and stored
within the register
When a government department shares information
with a third party, which is not covered by any High Level
other legal agreement, they require the information
receiving party to sign a contract. What are we building? Below is a high-level diagram
of the components. Each component isn’t a lot
of code as we aim to show a simple, but working
A ‘System Access Agreement’ describes a code of system and how each component interacts.
conduct for external parties to access any of the
department’s information systems and the general
terms of usage.
© 2017 Progress. All Rights Reserved.
Progress.com 10
Group Artefacts by Function—Not by Type Files organized by function, with views next to their
controllers.
In many starter examples of Angular projects, the
SPA is grouped by type of the object. Whether it is See Todd Motto’s Angular Style guide for in-depth
a View, Model or Controller—they are often lumped examples: https://github.com/toddmotto/angular-
and grouped in separate directories. You see a styleguide
component like DataService fairly regularly as the
only component to talk to the backend.
Progress.com 11
Entry – index.js
app.service(‘contractService’, ContractService);
app.component(‘app’, App);
app.component(‘contractList’, ContractList);
app.component(‘contractForm’, ContractForm);
<div ng-app="app">
<app>Loading...</app>
</div>
© 2017 Progress. All Rights Reserved.
Progress.com 12
The App and the App Component
The App component is loaded in the default page Webpack excels at loading and packing HTML as
replacing the <app> element. string into a single JavaScript file. So one of the early
choices we end up with is to rely on Webpack to do
Here we see a simple example of Angular 1.5’s new templating, and essentially do away with Angular
components syntax, combining best practices of Template Cache.
directives with isolated scopes and controllerAs
$ctrl by default, forward looking towards a web- Note: Should you still want to use Angular Template
components future in Angular 2.0. Cache, there is a Webpack ng-cache loader that will
take template files and preload them so they are still
<contract-list></contract-list> available via the templateUrl property.
function App() {
// App is just a top level component
}
Progress.com 13
The Contract List
Our first interesting component is a list of the
contracts we want to show in the application.
The template will look extremely simple.
<h1>Contract Register</h1>
<kendo-grid options="$ctrl.gridOptions"></kendo-grid>
Progress.com 14
Angular 1.5 Controller
module.exports = {
template: require(‘./contractList.html’),
controller: ContractListController
};
$ctrl.source = null;
$ctrl.openFormWindow = openFormWindow;
$ctrl.refresh = refresh;
$ctrl.newContract = newContract;
activate();
...
}
The ControllerList is written with readability in mind. code to keep the code simple. (Previously before 1.5,
We follow several best practices from Todd Motto’s we used vm from our MVVM background).
excellent Angular Style Guide. We list controller
members near the top, and initialize them with Because Webpack will take care of bundling and
activate() method. uglification of the parameters, use $inject header to
tell Angular which arguments need to be provided
In Angular 1.5, the controllerAs is on by default, and by dependency injection.
the default name is "$ctrl" so we reflect that in the
© 2017 Progress. All Rights Reserved.
Progress.com 15
The Controller activate()
function activate() {
$ctrl.source = new kendo.data.DataSource({
data: [],
schema: {
model: {
fields: {
...
}
}
}
});
$ctrl.gridOptions = {
dataSource: $ctrl.source,
sortable: true,
filterable: true,
groupable: true,
columns: [
...
],
toolbar: [
{
name: "add",
text: "New Contract",
template: ‘<a ng-click="$ctrl.newContract()" class="k-button k-button-icontext
k-grid-add" href="\\#">New Contract</a>’
}]
};
$ctrl.refresh();
}
© 2017 Progress. All Rights Reserved.
We set up the Kendo UI data source. And finally, we call refresh on the list. Refresh is a
method we will come back to later. It is exposed as a
We set up grid options for the Kendo Grid public method on the controller.
component.
Progress.com 16
The Controller refresh()
function refresh() {
contractService.getItems().then(function (items) {
$ctrl.source.data(items);
});
}
Progress.com 17
Control Approach: Bootstrap’s $modal, Office
UI Fabric UIF-Dialog, Kendo UI Kendo-Window
Progress.com 18
function openFormWindow(dataItem) {
// http://plnkr.co/edit/PjQdBUq0akXP2fn5sYZs?p=preview
var windowInstance = $kWindow.open({
options: {
modal: true,
title: dataItem.Title,
resizable: true,
visible: false
},
template: ‘<contract-form contractid="$ctrl.contractid"
$close="$close(result)" $dismiss="$dismiss(reason)"></contract-form>’,
controller: [‘contractid’, function (contractid) {
var $ctrl = this;
$ctrl.contractid = contractid;
}],
controllerAs: ‘$ctrl’,
resolve: {
contractid: function () {
return dataItem.Id;
}
}
});
windowInstance.result.then(function (result) {
if (result) {
$scope.result = ‘confirmed!’;
$ctrl.refresh();
}
else {
$scope.result = ‘canceled!’;
}
});
}
© 2017 Progress. All Rights Reserved.
Progress.com 19
The $kWindow service lets us open a window, and More information is available on https://angular-ui.
at the same time bind an Angular template and a github.io/bootstrap/#/modal.
controller to this template. The service also attaches
$close and $dismiss methods to the controller for Kendo UI window-service is available here and the
the form. So the child component can control when code itself is on GitHub.
it is ready to be closed.
One specific implementation note—because our
Angular’s template binding kicks in and allows the project utilizes Webpack bundling, we do not have
contract-form component to be rendered within the the template ‘window.html’ which is needed by
popped up modal dialog. angular-kendo-window service. Instead, we bundle
the content of window.html via a template string in
Finally, the service returns an instance that has our implementation.
a result promise that can be used by the parent
controller to watch for the result of the opened
dialog window.
... snipped
};
}])
Progress.com 20
The Contract Form
The Contract Form is our third component in the
application. It is in many ways similar to the contract
list component. Because it is loaded in a dialog
window, it also has unique bindings to the dialog
window’s $close and $dismiss methods.
module.exports = {
template: require(‘./contractForm.html’),
controller: ContractFormController,
bindings: {
‘$close’: ‘&’,
‘$dismiss’: ‘&’,
‘contractid’: ‘<’
}
};
activate();
function activate() {
//ID is known get item refresh
if($ctrl.contractid){
contractService.getItem($ctrl.contractid).then(function (item) {
$ctrl.item = item;
});
}
}
© 2017 Progress. All Rights Reserved.
Progress.com 21
The contract is set to the controller’s item property. This is then bound to the template for contract form.
<fieldset>
<legend>Contract Details</legend>
<p class="forms">
<label>Contract Type</label>
<select kendo-drop-down-list style="width: 100%;" ng-model="$ctrl.item.Title">
<option value="SAA" selected>System Access Agreement</option>
<option value="NDA">Non Disclosure Agreement</option>
</select>
</p>
<p>
<label>System Name</label>
<input type="text" class="k-textbox" ng-model="$ctrl.item.SystemName" required />
</p>
<p>
<label>Give a detailed description of the system </label>
<textarea ng-model="$ctrl.item.InformationDescription" required></textarea>
</p>
<p>
<label>End Date</label>
<input kendo-date-picker ng-model="$ctrl.item.ContractEndDate" required />
</p>
</fieldset>
© 2017 Progress. All Rights Reserved.
Progress.com 22
Kendo UI controls here can be bound simply to the model on the controller.
<p>
<button kendo-button type="submit" ng-click="$ctrl.save()">Save</button>
<button kendo-button type="button" ng-click="$ctrl.dismiss()">Cancel</button>
</p>
function save() {
... snip
//ID is known update item
if ($ctrl.contractid) {
contractService.updateItem($ctrl.item).then(function (item) {
$ctrl.close();
});
}
else {
//no ID add as new item
contractService.newItem($ctrl.item).then(function (item) {
$ctrl.close();
});
}
}
function close() {
$ctrl.$close({
result: ‘save’
});
}
function dismiss() {
$ctrl.$dismiss({
reason: ‘cancel’
});
}
© 2017 Progress. All Rights Reserved.
Progress.com 23
The buttons at the bottom of the form can also be item. This lets the UX bind to the latest version of
bound to methods on the controller. When invoked, the object, and if we are using calculated fields in
they call the contract-service to update or create SharePoint, this is necessary to bring back the server
new contract item. When that’s successful, they updates during the save.
call the $close or $dismiss methods on the dialog
window to close down the dialog, disposing the form Validation
component.
We bind any validation messages to the bottom of
If we don’t want to have save() close the modal the form. Kendo UI validation is very simple to set
window, then we need to take the saved item object up.
from the resolved promise and assign it back to $ctrl.
© 2017 Progress. All Rights Reserved.
Progress.com 24
Fields that are required, add a required attribute. Specify a kendo-validator in the form, and attach validate
method to the submit event of the form. (This is triggered by the save button, which is a type="submit").
<fieldset>
<legend>Contract Details</legend>
<p>
<label>System Name</label>
<input type="text" class="k-textbox" ng-model="$ctrl.item.SystemName"
required />
</p>
<p>
<label>Start Date</label>
<input kendo-date-picker ng-model="$ctrl.item.ContractStartDate" required
/>
</p>
</fieldset>
<p>
{{ $ctrl.validationMessage }}
</p>
</form>
function validate(event) {
//block submit from making a postback
event.preventDefault();
if ($ctrl.validator.validate()) {
$ctrl.validationMessage = "";
$ctrl.validationClass = "valid";
} else {
© 2017 Progress. All Rights Reserved.
Progress.com 25
To be fair, UI-Bootstrap also has similar validation capabilities. Office UI Fabric components does not currently
have validation, but it is on the roadmap in the future.
function save() {
if (!$ctrl.validator.validate()) {
$ctrl.validationMessage = "There is invalid data in the form.";
$ctrl.validationClass = "invalid";
return;
}
//ID is known update item
if ($ctrl.contractid) {
contractService.updateItem($ctrl.item).then(function (item) {
$ctrl.close();
});
}
else {
//no ID add as new item
contractService.newItem($ctrl.item).then(function (item) {
$ctrl.close();
});
}
}
Update contract-form’s save() method—it should check and make sure the form is valid.
PDF Generation
Progress.com 26
function generatePdf(selector) {
kendo.drawing.drawDOM($(selector)).then(function (group) {
kendo.drawing.pdf.saveAs(group, "contract.pdf");
});
}
Progress.com 27
contractService.js
module.exports = ContractService;
function ContractService($q) {
var self = this;
self.getItems = getItems;
self.newItem = newItem;
self.getItem = getItem;
self.updateItem = updateItem;
function getItems() {
return $q(function (resolve, reject) {
...
}
What is this library? Currently, it contains a fluent SharePoint REST API, developers still need to know
API for working with the full SharePoint REST API how to complete basic operations with the REST
as well as utility and helper functions. This takes the endpoints to take advantage of all the options
guess work out of creating REST requests, letting available.
developers focus on the what and less on the how.
(Source: PnP JS Core Wiki) Together with the PnP JS Core API documentation,
performing list operation in SharePoint has never
© 2017 Progress. All Rights Reserved.
Even though using the library simplifies working been this easy.
Progress.com 28
Let’s compare creating a SharePoint list through a
‘normal’ jQuery (ajax) SharePoint REST API call vs
the PnP JS Core Library:
jQuery.ajax({
url: "http://<site url>/_api/web/lists",
type: "POST",
data: JSON.stringify({
‘__metadata’: { ‘type’: ‘SP.List’ },
‘Title’: ‘My List Title’,
‘Description’: ‘My list description’,
‘BaseTemplate’: 100,
‘AllowContentTypes’: false,
‘EnableVersioning’: true,
}),
headers: {
"accept": "application/json;odata=verbose",
"content-type": "application/json;odata=verbose",
...
}).then(..
Making this same list configuration call through the PnPJSCore add method would look like:
As you can see this PnP example is much leaner and be added to the list creation request body. For
readable. The add method parameters allow us to finding all additional settings, we would still rely on
© 2017 Progress. All Rights Reserved.
specify the required properties to create the list with documentation available around the SharePoint
one line of JavaScript. REST API like the available list properties.
Progress.com 29
Chaining Promises—Always Be Making
Promises
function getItems() {
return $q(function(resolve,reject){
getList().then(function (list) {
list.items.get().then(function (items) {
resolve(items);
});
}).catch(reject);
});
}
function getList() {
return $q(function (resolve, reject) {
pnp.sp.web.lists.ensure(‘ContractRegister’, ‘’).then(function (result) {
if (result.created) {
setupContractRegister(result.list).then(function (list) {
resolve(list);
});
} else {
resolve(result.list);
}
© 2017 Progress. All Rights Reserved.
});
}).catch(reject);;
}
Progress.com 30
All of the contract service methods: getItems(),
newItem(), getItem(), updateItem() use the getList()
method to get the contract register list instance first.
In the contract service when the list is created we Batching Requests, the Easy Way
call the setupContractRegister() method only once.
Although batching has been available through the
Any consecutive call of the ensure method will SharePoint Online REST API for some time, making
effectively be the same as calling the getByTitle () batching request work was a fairly complicated task.
method directly. Batching was added in the PnPJSCore 1.0.2 release,
the announcement has some great examples for
batching (as well as caching). It is important to note
that batching is not supported on SharePoint 2013
On-premise as of yet.
© 2017 Progress. All Rights Reserved.
Progress.com 31
In our contract service, we use batching to provision the list fields for the contract register.
function setupContractRegister(list) {
return $q(function (resolve, reject) {
// create batch
var batch1 = pnp.sp.createBatch();
$q.all([
//Information System Details fields
list.fields.inBatch(batch1).addText(‘SystemName’),
list.fields.inBatch(batch1).addMultilineText(‘InformationDescription’, 8, false),
list.fields.inBatch(batch1).addNumber(‘InformationSensitivity’),
...
]).then(function () {
// add some demo entries
$q.all([
list.items.add({‘Title’: ‘SAA-001’, ‘ThirdPartyContactFullName’: ... }),
list.items.add({‘Title’: ‘SAA-002’, ‘ThirdPartyContactFullName’: ... }),
list.items.add({‘Title’: ‘SAA-003’, ‘ThirdPartyContactFullName’: ... })
]).then(function () {
resolve(list);
});
});
batch1.execute();
});
}
As explained in the version 1.0.2 announcement, the get the benefits of REST batching. When we want
same applies here. The key thing is we can keep to add the list fields without batching, (for example
chaining our promises or add them to an array of to make this work on-premises) we would need to
$q.all([ … ]) promises and they won’t be resolved chain them one after the other. Calling them in parallel
© 2017 Progress. All Rights Reserved.
until the batch execute command is called. (array of promises) will return conflict errors as list
configuration can’t be changed by multiple requests
We can almost write the same code as before and at the same time.
just add in the inBatch() method to the chain and
Progress.com 32
This is different for list items as they can be added
simultaneously as the above method demonstrates.
This does however result in three separate http
requests, where if we would have used batching
there would have only been one. “You might not be cooking in the SharePoint
Dev Kitchen, but that really doesn’t stop you
from watching and learning how to use the
same tools to cook at home.”
Building the
App: Behind the
Scenes
There’s always two sides to a great meal—there
is the recipe and there are the tools that do the
cooking. AngularJS, Kendo UI and PnP JS Core work
well to create the application. And then we look
to the build side—which tools do we use to really
improve the build experience.
© 2017 Progress. All Rights Reserved.
Progress.com 33
Typings
Intellisense is for Everyone, Not Just
TypeScript
With Visual Studio Code, detailed intellisense can be The default jsconfig.json file essentially tells Visual
enabled for both TypeScript and JavaScript projects. Studio Code what EMCAScript level we are running,
In a TypeScript project, the settings would be stored and which directories to ignore parsing (node_
in a tsconfig.json file. For a plain JavaScript project, modules) as that would make the editor unbearably
we need to add a jsconfig.json file. slow.
Progress.com 34
Gulp
Gulp is our chosen build system—a Gulp script is
JavaScript script. It makes it easier to specify how we
want to chain our operations or sometimes dive into
a few simple functions. Various sets of our tools work
with Gulp as Gulp extensions.
gulp.task("lint", () => {
return gulp.src("./src/**/*.js")
.pipe(eslint())
.pipe(eslint.format());
});
gulp.task("webpack:build", function(callback) {
// run webpack
webpack(config, function(err, stats) {
if(err) throw new gutil.PluginError("webpack:build", err);
gutil.log("[webpack:build]", stats.toString({
colors: true
}));
callback();
});
});
Progress.com 35
We can also type ‘task ‘ to bring up a list of other Gulp tasks that can be run from Visual Studio Code.
© 2017 Progress. All Rights Reserved.
Progress.com 36
gulp-eslint - eslint Checks the JavaScript Within Visual Studio Code, an extension is available
for eslint so we can get syntax checking while we
Particularly, we are looking for areas where a variable work on each file.
might be undefined. This is an extremely common
issue where perhaps we’ve used the wrong casing, gulp-spsave
or we had renamed the variable, but had leftovers,
or—and everyone’s guilty of this—we’ve copied code To really simplify getting our result files into
from the Internet (or from another function) and SharePoint, a few Gulp tools have been built. The
haven’t gone through and renamed everything. most common are gulp-spsync and gulp-spsave.
Another error that eslint can pick up is when we’ve Gulp-spsync is designed for SharePoint Online, but
had mismatched brackets or braces. Usually, an has been forked to gulp-spsync-withcred that lets us
advanced editor like VS Code will pick this up, but use it for both Online and On-Premises.
eslint will double check it for us.
Gulp-spsave is designed for both Online and On-
There are some best-practice rules, such as no-alert, Premises. The configuration options for both tools
where it will warn us if we’ve left alert() calls for are similar and they work similarly. Gulp-spsave has
testing behind and it’ll end up in production. a slight edge on the number of options as well as a
rewritten stack in gulp-spsave that uses sp-request
On style issues, we are lenient on issues related to module; it copies files faster.
linebreak characters, tabs and spaces. But on larger
teams this may be dictated to avoid edit wars and
huge merge nightmares.
Progress.com 37
We started our tools on gulp-spsync, then to gulp-
spsync-withcred so we can have one tool for both
Online and On-Premises deployments. Finally, we
moved over to gulp-spsave because it had more
options and runs faster.
return gulp.src(‘./dist/SiteAssets/**/*’)
.pipe(spsave({
"username": o365.username,
"password": o365.password,
"siteUrl": o365.site,
"folder": ‘SiteAssets’
}));
});
Progress.com 38
Webpack Bundling
Running Webpack in Development Mode external modules. In this configuration, the SPApp.
html is generated and points to reference vendor
In development, our solution is to use jQuery, libraries in a CDN.
Angular and Kendo UI (JavaScript and CSS) as
<script src="../SiteAssets/vendor.js"></script>
<script src="../SiteAssets/app.js"></script>
<div ng-app="app">
<app>Loading...</app>
</div>
Additionally, we upload local fallback versions in case This means that Webpack is packaging only a
the CDN is unavailable. vendor.js file for some remaining libraries we use, as
http://docs.telerik.com/kendo-ui/intro/installation/ well as the app.js containing all the application code
cdn-service that we wrote, along with the source map files for
these.
© 2017 Progress. All Rights Reserved.
Progress.com 39
Now, the HTML page can’t run directly in SharePoint Instead, the HTML can be included into a blank
Online. SharePoint Online will actually not serve page and run via the Content Editor webpart.
HTML pages; it will attempt to download them to
the computer.
© 2017 Progress. All Rights Reserved.
Progress.com 40
This is a one-time setup so we didn’t include this in changes in this area as SharePoint Framework is
the Gulp scripts. released.
In the future, with the SharePoint Framework, we If we look at the network tab in the browser’s F12
expect there will be a Gulp task that will deploy Development Mode, we can see a clearer picture of
artefacts to SharePoint as well as register them where the files are being loaded from.
with SharePoint APIs. We expect there will be small
The Kendo UI CSS, jQuery, Angular and Kendo JS Webpack packs everything into modules—a highly
files are loaded from CDN. Then a single vendor.js is unreadable mess, as one would expect.
loaded (this is where we packed additional vendor
libraries into a single file) along with our app.js file—
it is packed to only 17kb.
© 2017 Progress. All Rights Reserved.
Progress.com 41
But a quick Pretty-Print will help make more sense of it.
We are now able to set break points and debug our JavaScript even though it is minified in
SharePoint.
© 2017 Progress. All Rights Reserved.
Progress.com 42
Note: We can map the correct lines and set breakpoints, but remember that local variables have been
renamed to simple "e", "t" variable names. While we may be expecting "items", it is actually "e" that we should
be looking for.
The gulp-spsave documentation already gives an example of how to use a Gulp task to monitor file changes
and upload them automatically to SharePoint. This will save us from manually having to run the build/deploy
task again. Since we use Webpack to bundle our files, we combine webpack’s watch mode with the gulp-
watch plugin to upload changes.
gulp.task("webpack:build-dev-watch", function () {
//set webpack watch
var devWatchConfig = Object.create(devConfig);
devWatchConfig.watch = true;
// run webpack
webpack(devWatchConfig, function (err, stats) {
if (err) throw new gutil.PluginError("webpack:build-dev-watch", err);
gutil.log("[webpack:build-dev-watch]", stats.toString({
colors: true
}));
});
});
The ‘webpack:build-dev-watch’ tasks sets ‘watch debugging experience. The disadvantage here is
© 2017 Progress. All Rights Reserved.
= true’ in the Webpack config. In addition, the dev that the output file sizes will be larger, so depending
build doesn’t minify and uglify the JavaScript, which on the size and upload speed, we may want to use a
speeds up the compile time and gives a better minified/uglified build and rely on the source map.
Progress.com 43
In watch mode (and caching enabled) Webpack Webpack automatically watches the source directory
keeps each module in memory and only recompiles we are working in, so if we update and save any
changed output files. Since all our source files are of our work, Webpack will automatically rebuild
bundled in the app.js file, any change to, for example, the bundled modules and serve them all from
index.js or contractservice.js will trigger Webpack to memory, without need to write to file, then upload
generate a new app.js, but it won’t touch vendor.js or to SharePoint. This gives us extremely fast testing
app.css files (if nothing has changed in the related cycles.
files of course).
Webpack-dev-server has an automatic refresh
The Gulp file watcher monitors the "/dist/SiteAssets/" option with --inline mode, so when Webpack detects
folder for new changes that are then uploaded by a change within the source code, it will even trigger
spsave every time Webpack rebuilds them. the SharePoint page to refresh.
Calling the ‘deploy-watch’ task will build all the In the SharePoint Framework, Microsoft talks of a
output files once, upload them and after that only SharePoint Workbench tool that will allow us to test
upload changes. our customizations ‘offline.’ We expect the webpack-
dev-server to be a related part of this offline story.
Running Webpack in Memory—the Webpack
Dev Server
Progress.com 44
Running Webpack Dev Server with Hot For example, if we aren’t using Kendo UI ListView
Module Replacement control it doesn’t get bundled in the vendor.js file,
making a custom vendor file that’s a lot smaller.
The ultimate craziness in the Webpack world is hot
module replacement. Because Webpack loads each In practice, we find the bundling more difficult to
dependency as a separate module, it is able to watch work with when we are testing or debugging issues
for changes to individual modules and replace them with the controls. So while this is an exciting option,
at runtime. it should be reserved only for production code.
Progress.com 45
Getting Started Conclusion
How to run the Contract-Register demo These are the most exciting times as a developer,
1. You will need to have NodeJS installed especially for a SharePoint developer. There are
2. Fork from https://github.com/johnnliu/ many new tools for modern web technology, and all
contract-register or download as Zip of them are applicable to us to work in SharePoint
3. In a Node command-line, go to the contract- On-Premises and SharePoint Online.
register directory and run
»» > npm install The new tools and web stack work well together, but
»» This installs all the defined packages within there is no pressure to have to learn everything at
the package.json file once. We are learning, and sharing our learnings. We
4. Run Gulp tasks see new pieces and we try to figure out where they
»» > gulp build fit. We hope you will take what we’ve learned and run
»» This will build the project further with it and be successful.
5. Deploy to your SharePoint
»» Update o365-user.js with your account
details and site url
»» > gulp deploy
»» This will build and deploy the JavaScript to
your SharePoint site’s SiteAssets document
library.
6. One-off
»» Create a page with a Content Editor
webpart, and point it to the SiteAssets/
SPApp.html file.
Summary
In summary, we built a modern Angular application
with components using the latest work in PnP
JS Core. We built and pack the source code with
Webpack, and deploy it to SharePoint with Gulp.
© 2017 Progress. All Rights Reserved.
Progress.com 46
About the authors
Progress.com 47
John Liu
John is a Senior Consultant based in Sydney
for SharePoint Gurus. He specializes and blogs
frequently on client-side scripting, custom
development, workflows and Forms.
Progress (NASDAQ: PRGS) offers the leading platform for Progress, 14 Oak Park, Bedford, MA 01730 USA
developing and deploying mission-critical business applications. Tel: +1 781 280-4000 Fax: +1 781 280-4095
Progress empowers enterprises and ISVs to build and deliver On the Web at: www.progress.com
cognitive-first applications, that harness big data to derive Find us on facebook.com/progresssw
business insights and competitive advantage. Progress offers twitter.com/progresssw
leading technologies for easily building powerful user interfaces youtube.com/progresssw
across any type of device, a reliable, scalable and secure backend For regional international office locations and contact
platform to deploy modern applications, leading data connectivity information, please go to
to all sources, and award-winning predictive analytics that brings www.progress.com/worldwide
the power of machine learning to any organization. Over 1700
© 2017 Progress. All Rights Reserved.
Progress is trademark or registered trademark of Progress Software Corporation and/or one of its subsidiaries or affiliates in the
U.S. and/or other countries. Any other trademarks contained herein are the property of their respective owners.
© 2016 Progress Software Corporation and/or its subsidiaries or affiliates. All rights reserved. Rev 16/09 | 160325-0050
Progress.com 48