Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / productivity / SharePoint / SharePointOnline

SharePoint REST API and AngularJs for 2013, 2016 and Online

3.86/5 (5 votes)
2 Aug 2016CPOL5 min read 40.7K   617  
SharePoint and AngularJs and HTTP requests like GET, POST, UPDATE, DELETE and file uploading using AngularJS
This article is all about SharePoint and AngularJs and also handling HTTP requests like GET, POST, UPDATE, DELETE and file uploading using AngularJS in SharePoint 2013, 2016 and online.

Introduction

This sample contains a reusable angularjs module. The module contains a service and a directive. Anyone can use this module through dependence injection. This is for those people who want to take the advantage of two way data binding in SharePoint client side development. In client side development, basically we make some GET, POST, UPDATE and DELETE request to some particular end-points. So this module will save you from code redundancy for making any HTTP requests. This module is applicable for content editor web part and SharePoint Hosted app development.

Before You Begin

Target users require the following knowledge before using this module. I am providing some references of that stuff below:

  1. AngularJs
  2. REST API and SharePoint list
  3. SharePoint and AngularJs

Current Problem

A typical GET request to get all lists looks like the following:

JavaScript
function getAllLists() {
    $http({
        url: "/_api/web/lists"
            method: "GET",
        headers: {
            "accept": "application/json;odata=verbose",
            "content-Type": "application/json;odata=verbose"
        }
    }).success(function(result) {
        //do something here
    }).error(function(error, status) {
        // do something here
    });
}

And a GET request to get all items from a particular list looks like the following:

JavaScript
function getAllItems() {
    $http({
        url: "/_api/web/lists/GetByTitle('List Title')/Items"
            method: "GET",
        headers: {
            "accept": "application/json;odata=verbose",
            "content-Type": "application/json;odata=verbose"
        }
    }).success(function(result) {
        //do something here
    }).error(function(error, status) {
        // do something here
    });
}

The purpose of these functions is different but they are sharing most of the code. So this module is taking all the hassle of handling GET, POST, UPDATE and DELETE request. You will just pass your data and url to make any kind of request. The source code of this module is given below:

JavaScript
(function() {
    'use strict';

    angular.module('spNgModule', []).factory
    ("spBaseService", spBaseService).directive("customFileChange", customFileChange);;

    spBaseService.$inject = ["$q", "$http", "IS_APP_WEB"];

    function spBaseService($q, $http, isAppWeb) {

        var baseUrl = isAppWeb ? _spPageContextInfo.webAbsoluteUrl : 
                                 _spPageContextInfo.siteAbsoluteUrl;

        return {
            getRequest: getRequest,
            postRequest: postRequest,
            updateRequest: updateRequest,
            deleteRequest: deleteRequest,
            fileUploadRequest: fileUploadRequest,
            baseUrl: baseUrl
        };

        function getRequest(query, endPoint) {
            var deferred = $q.defer();
            $http({
                url: endPoint || baseUrl + query,
                method: "GET",
                headers: {
                    "accept": "application/json;odata=verbose",
                    "content-Type": "application/json;odata=verbose"
                }
            }).success(function(result) {
                deferred.resolve(result);
            }).error(function(result, status) {
                deferred.reject({
                    error: result,
                    status: status
                });
            });
            return deferred.promise;
        }

        function postRequest(data, url, endPoint) {
            var deferred = $q.defer();
            $http({
                url: endPoint || baseUrl + url,
                method: "POST",
                headers: {
                    "accept": "application/json;odata=verbose",
                    "X-RequestDigest": document.getElementById("__REQUESTDIGEST").value,
                    "content-Type": "application/json;odata=verbose"
                },
                data: JSON.stringify(data)
            }).success(function(result) {
                deferred.resolve(result);
            }).error(function(result, status) {
                deferred.reject({
                    error: result,
                    status: status
                });
            });
            return deferred.promise;
        }

        function fileUploadRequest(data, url, endPoint) {
            var deferred = $q.defer();
            $http({
                url: endPoint || baseUrl + url,
                method: "POST",
                processData: false,
                data: data,
                transformRequest: angular.identity,
                headers: {
                    "accept": "application/json;odata=verbose",
                    "X-RequestDigest": document.getElementById("__REQUESTDIGEST").value,
                    "Content-Type": undefined
                }
            }).success(function(result) {
                deferred.resolve(result);
            }).error(function(result, status) {
                deferred.reject({
                    error: result,
                    status: status
                });
            });
            return deferred.promise;
        }

        function updateRequest(data, url, endPoint) {
            var deferred = $q.defer();
            $http({
                url: endPoint || baseUrl + url,
                method: "PATCH",
                headers: {
                    "accept": "application/json;odata=verbose",
                    "X-RequestDigest": document.getElementById("__REQUESTDIGEST").value,
                    "content-Type": "application/json;odata=verbose",
                    "X-Http-Method": "PATCH",
                    "If-Match": "*"
                },
                data: JSON.stringify(data)
            }).success(function(result) {
                deferred.resolve(result);
            }).error(function(result, status) {
                deferred.reject({
                    error: result,
                    status: status
                });
            });
            return deferred.promise;
        }

        function deleteRequest(url, endPoint) {
            var deferred = $q.defer();
            $http({
                url: endPoint || baseUrl + url,
                method: "DELETE",
                headers: {
                    "accept": "application/json;odata=verbose",
                    "X-RequestDigest": document.getElementById("__REQUESTDIGEST").value,
                    "IF-MATCH": "*"
                }
            }).success(function(result) {
                deferred.resolve(result);
            }).error(function(result, status) {
                deferred.reject({
                    error: result,
                    status: status
                });
            });
            return deferred.promise;
        }
    }

    customFileChange.$inject = ["$parse"];

    function customFileChange($parse) {
        return {
            restrict: "A",
            link: function(scope, element, attrs) {
                var model = $parse(attrs.customFileChange);
                var modelSetter = model.assign;
                element.bind("change", function() {
                    scope.$apply(function() {
                        var reader = new FileReader();
                        reader.onload = function(e) {
                            var fileModel = {
                                fileName: element[0].files[0].name,
                                fileAsBuffer: e.target.result
                            };
                            modelSetter(scope, fileModel);
                        }
                        reader.onerror = function(e) {
                            alert(e.target.error);
                        }
                        reader.readAsArrayBuffer(element[0].files[0]);
                    });
                });
            }
        };
    }

})(window, document);

What's Included in this Module

  • getRequest(query, endPoint)
  • postRequest(data, url, endPoint)
  • updateRequest(data, url, endPoint)
  • deleteRequest(url, endPoint)
  • fileUploadRequest(data, url, endPoint)

endPoint is optional in everywhere. I will discuss the usages of it later on. You will be able to use these endpoints that support GET, POST, UPDATE and DELETE request. Every method will return you a promise and you will have to handle it in your code.

How to Use

At first, download this module from attachment. Attachment contains minified and non-minified version of my module. After downloading the file, add the reference in your project. For example, In SharePoint hosted app, It should look like the following:

HTML
<script src="../Scripts/App/spNgModule.js"></script>

In Content Editor Web Part, you have to upload this file in some library, then you will use it.

Adding Dependence in Your Module

You can add this dependence in your module in the following way. The name of this module is spNgModule.

JavaScript
(function () {
    angular.module("spNgModuleTest", ["spNgModule"])
    .constant("IS_APP_WEB", false);
})();

Here, you will have to specify the value of IS_APP_WEB. It means which Web URL will be used for making GET, POST, UPDATE and DELETE request. After specifying the value of IS_APP_WEB, you will be able to use other URL also for making any request. That's why there is an optional parameter named endPoint.

NB: If you specify endPoint in your request, then url parameter will be optional. By default, all requests will be made based on the value of IS_APP_WEB. Either it is APP Web or Host Web.

Injecting Service

The service name I have used is spBaseService. So you can inject this service in the following way:

JavaScript
angular.module("spNgModuleTest")
    .factory("spNgTestSvc", spNgTestSvc);

    spNgTestSvc.$inject = ["spBaseService"];

GET Request Example

JavaScript
spBaseService.getRequest(query, endPoint)

You can pass any query or end-point that supports HTTP GET request. For example:

You want to get all lists under the current site:

JavaScript
function getAllLists() {
    var query = "/_api/web/lists?$select=Title";
    return spBaseService.getRequest(query);
}

If you want get all items of a list, then it will be:

JavaScript
function getAllItems() {
    var query = "/_api/web/lists/GetByTitle('List Title')/Items";
    return spBaseService.getRequest(query);
}

If you want to get all sub sites, then it will be:

JavaScript
function getSubSites() {
    var query = "/_api/Web/Webs";
    return spBaseService.getRequest(query);
}

So what I wanted to say by these examples is: Just to make any GET request, you will have to deal with query or endPoint.

Use of endPoint Parameter

Someone may need endPoint in the following scenario:

Let's say your current site is https://xxx.sharepoint.com (can be host web or app web). Now you want to make a GET, POST, UPDATE or DELETE request to the sub site https://xxx.sharepoint.com/hr or a GET, POST, UPDATE or DELETE request to host web from the app web. In that case, you will need to use endPoint.

JavaScript
function getSubSites() {
    var endPoint = "https://xxx.sharepoint.com/hr/_api/Web/Webs";
    return spBaseService.getRequest(null, endPoint);
}

POST Request Example

It is applicable for adding new object (list item, file, site, document and so on).

JavaScript
spBaseService.postRequest(data, url, endPoint)

data is the quest body. It will vary from request to request. For example, to add a sub site, the request body should look like:

JavaScript
var data = {
    parameters: {
        __metadata: {
            'type': 'SP.WebInfoCreationInformation'
        },
        Url: "site url",
        Title: "site title",
        Description: "site description",
        Language: 1033,
        UseUniquePermissions: true
    }
};

url is the any end-point that supports POST request. For adding a sub site, the end-point is:

var url = "/_api/web/webinfos/add";

Usages of endPoint can be found here.

So the full POST request of adding a site is:

JavaScript
function addSubSite() {
    var data = {
        parameters: {
            __metadata: {
                'type': 'SP.WebInfoCreationInformation'
            },
            Url: "site url",
            Title: "site title",
            Description: "site description",
            Language: 1033,
            UseUniquePermissions: true
        }
    };
    var url = "/_api/web/webinfos/add";
    return spBaseService.postRequest(data, url);
}

UPDATE Request Example

JavaScript
spBaseService.updateRequest(data, url, endPoint);

It is almost the same as POST request. You can use this method to update any object in your site. Have a look at updating an item in a particular list.

function updateItemById(itemId) {
    var url = "/_api/web/lists/GetByTitle('List Name')/GetItemById(" + itemId + ")";

    var data = {
        __metadata: {
            type: "SP.Data.SpNgListListItem"
        },
        Title: "New sp ng item updated " + Math.random()
    };
    return spBaseService.updateRequest(data, url);
}

See here are the usages of endPoint.

DELETE Request Example

JavaScript
spBaseService.deleteRequest(url, endPoint);

You will use this method to remove something from your site. Let's say we want to remove an item having ID equals 5.

function deleteAnItem() {
    var url = "/_api/web/lists/GetByTitle('List Name')/GetItemById(5)";
    return spBaseService.deleteRequest(url);
}

See here for the usages of endPoint.

File Upload Example

spBaseService.fileUploadRequest(data, url, endPoint);

In request body, you will have to pass the file as ArrayBuffer. As I said earlier, this module also contains a directive so this directive will help you to get file as ArrayBuffer. The name of this directive is customFileChange. The HTML for uploading should look like:

HTML
<input type="file" data-custom-file-change="attachment" /> 

attachment is the model and it will give you the file as ArrayBuffer. You can change its name as per your liking. There are two properties you will get from this model such as fileName and fileAsBuffer.

Following is the example of uploading an attachment of a particular item having ID equals 2.

JavaScript
function uploadAttachment(attachment){
            var url = "/_api/web/lists/GetByTitle('SpNgList')/items(2)/
                       AttachmentFiles/add(FileName='" + attachment.fileName + "')";
            return spBaseService.fileUploadRequest(attachment.fileAsBuffer, url);
        }

See here are the usages of endPoint.

Handling Response Example

You will get a promise in return from all of the above methods. So it is the same as typical response handling Angular code. For example:

spNgTestSvc.addSubSite()
    .then(function(successResponse) {
        // code after success
    }, function(errorrResponse) {
        //code after error
    });

errorResponse has two properties such as error and status. error is the actual error object returned by SharePoint end-point.

Conclusion

That's all about my current module. I will try to make it better in future updates. As my source is open, I will be highly pleased if I get any feedback and suggestion from my readers.

History

  • 29th July, 2016: Initial version

License

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