Enables rapid development of SharePoint Apps/Add-ins using the JavaScript SharePoint App Model. This library provides a clean, concise API that simplifies async REST interaction. Easily read/write List items (CRUD), execute REST calls, and gather user/group information.
- Simple - Most REST/Web Service interaction can be done in a couple of lines of code
- Modern - Lightweight, pure JavaScript solution
- Elegant - Utilizes the new ES6 Promise architecture for asynchronous operations
- Robust - Built for SharePoint 2013 API and OData v3
- List Interface - Create, read, update, and delete (CRUD) List/Library items with a single line of code
- REST Interface - Run ad-hoc REST calls to any SharePoint REST API endpoint
- User Interface - Get current or specified User and Groups details
- Form Population - Populate form elements using data-bind declarative binding system like Knockout or AngluarJS
- SharePoint 2013 (SP2013), SharePoint 2016 (SP2016), SharePoint Online (O365)
- Enterprise license not required
- Installation
- Method Overview
- Method Reference
- Node.js and SharePoint Online
- Async Operations via Promises
- Issues / Suggestions
- Special Thanks
- License
<script lang="javascript" src="https://yourhost.com/subsite/SiteAssets/js/jquery.min.js"></script> <script lang="javascript" src="https://yourhost.com/subsite/SiteAssets/js/sprestlib.js"></script>
IE11 support requires a Promises polyfill as well (included in the libs
folder)
<script lang="javascript" src="https://yourhost.com/subsite/SiteAssets/js/sprestlib.bundle.js"></script>
Bundle includes all required libraries (SpRestLib + jQuery and Promises)
bower install sprestlib
npm install sprestlib var sprLib = require("sprestlib");
-
sprLib.list(listName).getItems(options)
- Returns an array of item objects using a variety of possible options -
sprLib.list(listName).create(item)
- Create a new list item using JSON data -
sprLib.list(listName).update(item)
- Update an existing item using JSON data -
sprLib.list(listName).delete(id)
- Delete an existing item by ID (permanently delete) -
sprLib.list(listName).recycle(id)
- Recycle an existing item by ID (move to Recycle Bin) -
sprLib.list(listName).cols()
- Returns an array of column objects with useful info (name, datatype, etc.) -
sprLib.list(listName).info()
- Returns information about the List/Library (GUID, numberOfItems, etc.)
sprLib.rest(options)
- Returns the results of a given REST call to any SharePoint REST API
sprLib.user(options).info()
- Returns user information object (Id, Title, Email, etc.) (SPUser)sprLib.user(options).groups()
- Returns user group objects (Id, Title, Owner, etc.) (SPGroup)
data-sprlib{options}
- Populates the parent tag using the options provided
sprLib.renewSecurityToken()
- Refreshes the SharePoint page security digest token
Lists can be accessed by either their name or their GUID:
Syntax: sprLib.list(listName)
or sprLib.list(listGUID)
By default, the library defaults to the local directory. There are occasions where operations would be pointed to other locations - reading from a subsite, etc. - and that can be done easily be setting the baseUrl at the list-level.
Syntax: sprLib.list(listName).baseUrl(urlPath)
Example:
sprLib.list('Employees').baseUrl('/sites/HumanResources/devtest/')
Syntax:
sprLib.list(listName|listGUID).getItems()
Returns:
- Array of objects containing name/value pairs
__metadata
is always included in the results array (to enable further operations, use of Etag, etc.)
Option | Type | Default | Description | Possible Values / Returns |
---|---|---|---|---|
listCols | array OR object | column names to be returned | array of column names OR object (see below) | |
cache | boolean | false | cache settings | Ex:cache: true |
queryFilter | string | query filter | utilizes OData style Query Operators | |
queryLimit | string | max items to return | 1-N | |
queryOrderby | string | column(s) to order by | Ex:queryOrderby:Name |
NOTE: Omitting listCols
will result in all List columns being returned (mimics SharePoint default behavior)
Option | Type | Default | Description | Possible Values / Return Values |
---|---|---|---|---|
dataName | string | the column name | the fixed, back-end REST column name (use Get List Column Properties) | |
dispName | string | the name to use when displaying results in table headers, etc. | ||
dateFormat | string | format to use when returning/displaying date | INTL , INTLTIME , YYYYMMDD , ISO , US | |
dataFunc | function | function to use for returning a result | use a custom function to transform the query result (see below) | |
getVersions | boolean | false | return append text versions in array | true or false |
There are many times where you'll need more than a simple column value. For example, I often provide a link to the InfoPath form so users can edit the item directly.
The dataFunc
option allows you access to the entire result set and to return any type of value. See sample below where "editLink" is created.
// EX: Simple array of column names sprLib.list('Employees') .getItems( ['Id', 'Name', 'Badge_x0020_Number'] ) .then(function(arrData){ console.table(arrData); }) .catch(function(errMsg){ console.error(errMsg) }); // Result: /* .---------------------------------------------------------. | __metadata | Id | Name | Badge_x0020_Number | |-----------------|-----|------------|--------------------| | [object Object] | 253 | Hal Jordan | 12345 | '---------------------------------------------------------' */
// EX: Using 'listCols' option with array of column names sprLib.list('Employees').getItems({ listCols: ['Name', 'Badge_x0020_Number', 'Hire_x0020_Date'] }) .then(function(arrData){ console.table(arrData) }) .catch(function(errMsg){ console.error(errMsg) });
// EX: Using 'listCols' option to name our columns // EX: Using 'getVersions' to gather all "Append Text"/Versioned Text into an array // EX: Using 'dataFunc' option to return a dynamic, generated value (an html link) // EX: Using query options: filter, order, limit sprLib.list('Employees').getItems({ listCols: { empId: { dataName:'ID' }, badgeNum: { dataName:'Badge_x0020_Number' }, appendText: { dataName:'Versioned_x0020_Comments', getVersions:true }, editLink: { dataFunc:function(objItem){ return '<a href="/sites/dev/Lists/Employees/DispForm.aspx?ID='+objItem.ID+'">View Emp</a>' } } }, queryFilter: 'Salary gt 100000', queryOrderby: 'Hire_x0020_Date', queryLimit: 3 }) .then(function(arrData){ console.table(arrData) }) .catch(function(errMsg){ console.error(errMsg) }); // RESULT: /* .--------------------------------------------------------------------------------------------------------------------------------. | empId | badgeNum | appendText | editLink | |-------|----------|------------------------------------|------------------------------------------------------------------------| | 334 | 1497127 | ["20170624:Update","20170601:New"] | <a href="/sites/dev/Lists/Employees/DispForm.aspx?ID=334">View Emp</a> | | 339 | 1497924 | ["Not here yet", "Emp created"] | <a href="/sites/dev/Lists/Employees/DispForm.aspx?ID=334">View Emp</a> | | 350 | 1497927 | ["Vice President promotion"] | <a href="/sites/dev/Lists/Employees/DispForm.aspx?ID=334">View Emp</a> | '--------------------------------------------------------------------------------------------------------------------------------' */
Syntax: sprLib.list(listName|listGUID).create(itemObject)
Options: An object with internal name/value pairs to be inserted
Returns: Object with key/value pairs
Example:
sprLib.list('Employees') .create({ Name: 'Marty McFly', Badge_x0020_Number: 12345, Hire_x0020_Date: new Date(), Active: true }) .then(function(objItem){ console.log('New Item:'); console.table(objItem); }) .catch(function(strErr){ console.error(strErr); });
Syntax: sprLib.list(listName|listGUID).update(itemObject)
Options:
- An object with internal name/value pairs to be inserted
- if
__metadata.etag
is not provided, this is equivalent to force:true (etag:'"*"'
is used)
Returns: The object provided
Example:
sprLib.list('Employees') .update({ ID: 99, Name: 'Marty McFly', Active: false }) .then(function(objItem){ console.log('Updated Item:'); console.table(objItem); }) .catch(function(strErr){ console.error(strErr); });
Syntax: sprLib.list(listName|listGUID).delete(itemId)
Options:
- if
__metadata.etag
is not provided, this is equivalent to force:true (etag:'"*"'
is used)
Returns: ID of the item just deleted
Notes: Permanently deletes the item (bypasses Recycle Bin; Is not recoverable)
Example:
sprLib.list('Employees') .delete(99) .then(function(intId){ console.log('Deleted Item:'+intId); }) .catch(function(strErr){ console.error(strErr); });
Syntax: sprLib.list(listName|listGUID).recycle(itemId)
Returns: ID of the item just recycled
Notes: Moves the item into the Site Recycle Bin
Example:
sprLib.list('Employees') .recycle(99) .then(function(intId){ console.log('Recycled Item:'+intId); }) .catch(function(strErr){ console.error(strErr); });
Syntax: sprLib.list(listName|listGUID).cols()
Returns: Array of columns with name value pairs of property values
Property | Type | Description |
---|---|---|
dispName | string | display name |
dataName | string | internal name - used in REST queries and in listCols arguments |
dataType | string | column type (FieldTypeKind) values: Boolean , Calculated , Currency , DateTime , Note , Number , Text |
defaultValue | boolean | the default value (if any) |
isAppend | boolean | is this an append text column? |
isNumPct | boolean | is this a percentage number column? |
isReadOnly | boolean | is this an read only column? |
isRequired | boolean | is a value required in this column? |
isUnique | boolean | are unique values enforced on this column? |
maxLength | boolean | the maximum length of the column value |
sprLib.list('Employees').cols().then(function(data){ console.table(data) }); // Result: /* .--------------------------------------------------------------------------------------------------------------------------------------. | dispName | dataName | dataType | isAppend | isNumPct | isReadOnly | isRequired | isUnique | defaultValue | maxLength | |--------------|--------------------|------------|----------|----------|------------|------------|----------|--------------|-----------| | ID | ID | Counter | false | false | true | false | false | | | | Name | Name | Text | false | false | false | false | false | | 255 | | Badge Number | Badge_x0020_Number | Number | false | false | false | true | true | | | | Hire Date | Hire_x0020_Date | DateTime | false | false | false | false | false | | | '--------------------------------------------------------------------------------------------------------------------------------------' */
Syntax: sprLib.list(listName|listGUID).info()
Returns: Array of list properties and their values
Property | Type | Description |
---|---|---|
AllowContentTypes | boolean | Whether Allow management of content types? is enabled |
BaseTemplate | integer | SPListTemplateType SP Base Template ID number - ex: 100 |
Created | date | Date the List/Library was created |
Description | boolean | List/Library Description |
EnableAttachments | boolean | Whether users can attach files to items in this list |
ForceCheckout | boolean | Whether Force checkout is enabled |
Hidden | boolean | Whether List is hidden |
Id | GUID | The SP GUID of the List |
ItemCount | number | The number of Items in the List |
Title | string | The Title of the List/Library |
sprLib.list('Employees').info().then(function(data){ console.table(data) }); // Result: /* .-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------. | AllowContentTypes | BaseTemplate | Created | Description | EnableAttachments | ForceCheckout | Hidden | Id | ItemCount | Title | |-------------------|--------------|----------------------|-------------|-------------------|---------------|--------|--------------------------------------|-----------|-----------| | true | 100 | 2016-08-21T20:48:43Z | | true | false | false | 8fda2799-dbbc-a420-9869-df87b08b09c1 | 25 | Employees | '-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------' */
Returns the results of a given REST call to any SharePoint REST API
Use the sprLib.rest()
interface to GET or PORT to any of the dozens of available SP REST API Endpoints.
The available REST service endpoints can add Users to Groups, create columns in a List/Library, enumerate site properties and other super useful functions.
Get Results
Calling the SharePoint REST APIs directly via AJAX calls will return results in different forms (some are data.d
while others are data.d.results
) whereas SpRestLib always returns consistent results in the form of array of objects with name/value pairs.
Syntax sprLib.rest(options)
Returns: Array of objects containing name/value pairs
Option | Type | Default | Description | Possible Values / Returns |
---|---|---|---|---|
url | string | current url | REST API endpoint | full or relative url. See: SharePoint REST API |
type | string | GET | rest type | GET or POST . Ex:type: 'POST' |
data | string | data to be sent | Ex:data: {'type': 'SP.FieldDateTime'} | |
cache | boolean | false | cache settings | Ex:cache: true |
contentType | string | application/json | request header content-type | Only used with type:'POST' |
queryCols | string | fields/columns to get | any available field from the SP REST API | |
queryFilter | string | query filter | utilizes OData style Query Operators Ex:queryFilter: 'Salary lt 99000' | |
queryLimit | string | 1000 | max items to return | 1-5000. Ex:queryLimit: 5000 |
queryOrderby | string | column(s) to order by | Ex:queryOrderby: Name |
// EX: Get site group info sprLib.rest({ url: '/sites/dev/_api/web/sitegroups', queryCols: ['Title','LoginName','AllowMembersEditMembership'], queryFilter: 'AllowMembersEditMembership eq false', queryOrderby: 'Title', queryLimit: 10 }) .then(function(arrayResults){ console.table(arrayResults) }) .catch(function(errMsg){ console.error(errMsg) }); /* .------------------------------------------------------------------------------. | Title | LoginName | AllowMembersEditMembership | |------------------------|------------------------|----------------------------| | Dev Site Owners | Dev Site Owners | false | | Dev Site Visitors | Dev Site Visitors | false | | Excel Services Viewers | Excel Services Viewers | false | '------------------------------------------------------------------------------' */ // EX: Create a new List column sprLib.rest({ url: "_api/web/lists/getbytitle('Employees')/fields", type: "POST", data: "{'__metadata':{'type':'SP.FieldDateTime'}, 'FieldTypeKind':4, 'Title':'Bonus Date', 'DisplayFormat':1 }" }) .then(function(){ console.log("New column created!"); }) .catch(function(errMsg){ console.error(errMsg) });
Omitting options will return information about the current user, otherwise, the specified user is returned.
sprLib.user()
sprLib.user(options)
Option | Type | Required? | Description | Possible Values / Returns |
---|---|---|---|---|
id | number | user id | user id to query. Ex: {id:99} | |
email | string | user email address | user email to query. Ex: {email:'brent@github.com'} | |
login | string | user login name | user loginName to query. Ex: `{login:'i:0#.f | |
title | string | user title | user title to query. Ex: {title:'Brent Ely'} |
Syntax: sprLib.user().info()
sprLib.user(options).groups()
Returns: Object with name/value pairs containing information about the SharePoint user
Note: Uses the basic SP User service (not the Enterprise licensed User Profile service)
// EXAMPLE: Get current user info sprLib.user().info() .then(function(objUser){ console.table([objUser]) }); // EXAMPLE: Get user info by email address sprLib.user({ email:'brent@microsoft.com' }).info() .then(function(objUser){ console.table([objUser]); }); // RESULT: /* .--------------------------------------------------------------------------------------------. | Id | LoginName | Title | Email | IsSiteAdmin | |----|---------------------------------------|-----------|---------------------|-------------| | 9 | i:0#.f|membership|brent@microsoft.com | Brent Ely | brent@microsoft.com | true | '--------------------------------------------------------------------------------------------' */
Syntax: sprLib.user().groups()
sprLib.user(options).groups()
Returns: Array of objects containing the user's SharePoint groups SPGroup
sprLib.user().groups() .then(function(arrGroups){ console.table(arrGroups) }); // RESULT: /* .-----------------------------------------------------------------------------------------. | Id | Title | Description | OwnerTitle | LoginName | |----|------------------|----------------------------|-----------------|------------------| | 6 | Dev Site Owners | Use for full control perms | Dev Site Owners | Dev Site Owners | | 7 | Dev Site Members | Use for contribute perms | Dev Site Owners | Dev Site Members | '-----------------------------------------------------------------------------------------' */
Perform control/form binding with an AngluarJS-like syntax made especially for SharePoint Web Services.
Many different HTML tags can be populated by adding an data-sprlib
property to many HTML element types.
Syntax: <tag data-sprlib='{ options }'>
The following HTML element tags can be populated:
- select: populates 1+ options
- static element (span, p, etc.): populates a single plain text value
- table: a table or tbody can be populates with 1+ columns
Option | Type | Required? | Description | Possible Values / Returns |
---|---|---|---|---|
list | string | yes | List or Library name | |
cols | array | columns to be populated | ||
text | string | text string to show | ||
value | string | value string to show | ||
filter | string | query filter value | Ex: filter="ID eq 100" | |
tablesorter | string | whether to add jQuery TableFilter to table | ||
options | string | table/tbody options | showBusySpinner |
<!-- select --> <select data-sprlib='{ "list":"Employees", "value":"Id", "text":"Name" }'></select> <!-- input --> <input type="text" data-sprlib='{ "list":"Departments", "value":"Title" }' placeholder="Departments.Title"></input> <!-- static elements span, div, etc. --> <span data-sprlib='{ "list":"Employees", "value":"Name", "filter":{"col":"Name", "op":"eq", "val":"Brent Ely"} }'></span> <!-- table/tbody --> <table data-sprlib='{ "foreach": {"list":"Employees", "filter":{"col":"Active", "op":"eq", "val":true}}, "options":{"showBusySpinner":true} }'> <tbody data-sprlib='{ "foreach": {"list":"Employees", "cols":["Name","Utilization_x0020_Pct"] } }'></tbody>
Refreshes the SharePoint page security digest token.
sprLib.renewSecurityToken()
Starting in SP2013, .aspx pages include a security digest token in a hidden input element that will expire after 30 minutes (by default).
This method allows the refresh of this value, which can be useful in certain cases.
NOTE: SpRestLib will refresh the token automatically as needed during CRUD operations.
SpRestLib can be utilized via Node.js to perform powerful operations, generate reports, etc.
See the example
directory for a complete, working demo of connecting to SharePoint Online.
SpRestLib asynchronous methods return Promises, which provide two main benefits:
- No more callback functions
- No more managing async operations
If you're unfamiliar with the new ES6 Promise functionality, you may want to the a moment to read more about them. They really are a game changer for those of us who deal with asynchronous operations.
All major browsers (and Node.js) now fully support ES6 Promises, so keep reading to see them in action.
Promises can be chained using then()
or grouped using Promise.all()
so callbacks and queue management are a thing of the past.
- Promises can be chained so they execute in the order shown only after the previous one has completed
- SpRestLib methods return a Promise, meaning the "return sprestlib" calls below cause the subsequent
.then()
to wait for that method's REST call to return a result - That's all you need to code to enable chaining of asynchronous operations without any callback functions or queue management!
var item = { Name:'Marty McFly', Hire_x0020_Date:new Date() }; Promise.resolve() .then(function() { return sprLib.list('Employees').create(item); }) .then(function(item){ return sprLib.list('Employees').update(item); }) .then(function(item){ return sprLib.list('Employees').delete(item); }) .then(function(item){ console.log('Success! An item navigated the entire CRUD chain!'); });
- Promises can be grouped using
.all()
meaning each of them must complete before.then()
is executed.
- This example requires that both the user info and user group queries complete before we move on
- The old AJAX callback method model required a lot more code to do the same thing!
Promise.all([ sprLib.user().info(), sprLib.user().groups() ]) .then(function(arrResults){ // 'arrResults' holds the return values of both method calls above - in the order they were provided // Therefore, arrResults[0] holds user info() and arrResults[1] holds user groups() console.log( "Current User Info `Title`: " + arrResults[0].Title ); console.log( "Current User Groups count: " + arrResults[1].length ); });
Please file issues or suggestions on the issues page on GitHub, or even better, submit a pull request. Feedback is always welcome!
When reporting issues, please include a code snippet or a link demonstrating the problem.
- Marc D Anderson - SpRestLib is built in the spirit of the late, great
SPServices
library - Microsoft - for the SharePoint.com developer account
- Everyone who submitted an Issue or Pull Request
Copyright © 2016-2017 Brent Ely