Search code examples
restsharepoint-2013providersharepoint-listhosted-app

Query multiple SharePoint lists Using REST API and angular JS


I have a scenario of fetching data from multiple SharePoint 2013 lists using REST API and Angularjs. I am able to fetch the data successfully from one of the SharePoint list but my requirements is to fetch the data from multiple lists on the page load. I am using a provider hosted app to fetch the data from host web. I have 2 methods for calling 2 separate lists. I am getting the results from first method successfully but when the second method is called after the execution of 1st method. I am getting a time out error. It seems like i cannot call the 2 methods one after the other. Below is my code, could anyone please help me if i am missing something or if there is any other way to fetch the data from multiple SharePoint lists.

Method 1: fetch Data from List 1

var query = listEndPoint + "/getbytitle('CandidateList')/items?$select=ID,FirstName,MiddleInitial,LastName,EmailAddress,PrimaryPhoneNo,ProfileImage,Address,State,Country,CurrentTitle,CurrentCompany,LastActivityModifiedBy,LastActivityModifiedDate,DeletedStatus&@target='" + hostweburl + "'";

    var getCandidates = function (query, queryCandidateNotes) 
                    {
                    alert('getRequest');
                    var scriptbase = hostweburl + "/_layouts/15/";
                    var deferred = $q.defer();
                    // Load 15hives js files and continue to the successHandler    
                    $.getScript(scriptbase + "SP.Runtime.js",
                        function () {`enter code here`
                            $.getScript(scriptbase + "SP.js",
                                function () {
                                    $.getScript(scriptbase +"SP.RequestExecutor.js",
                                         function () {
                                             var executor = new SP.RequestExecutor(appweburl);
                                             executor.executeAsync({
                                                 url: query,
                                                 method: "GET",
                                                 headers: { "Accept": "application/json; odata=verbose" },
                                                 success: successHandler,
                                                 error: errorHandler
                                             });
                                             //deferred.resolve();
                                         });
                                });
                        });

                    function successHandler(data) {
                        var jsonObject1 = JSON.parse(data.body);

                        deferred.resolve(jsonObject1);

                    }

                    function errorHandler(data, errorCode, errorMessage) {
                        alert('Error1:' + errorMessage + data.body);
                    }
                    // Get 
                    return deferred.promise;

                    //Candidate Details Ends
                };

Method 2: fetch Data from List 2

    var queryCandidateNotes = listEndPoint + "/getbytitle('CandidateNotes')/items?$select=Title,CandidateId&@target='" + hostweburl + "'";

 // Get All Candidate Notes
            var getCandidateNotes = function (queryCandidateNotes) {
                alert('getCandidateNotesRequest');
                var scriptbase = hostweburl + "/_layouts/15/";
                var deferred2 = $q.defer();
                // Load 15hives js files and continue to the successHandler    
                $.getScript(scriptbase + "SP.Runtime.js",
                    function () {
                        $.getScript(scriptbase + "SP.js",
                            function () {
                                $.getScript(scriptbase + "SP.RequestExecutor.js",
                                     function () {
                                         var executor = new SP.RequestExecutor(appweburl);
                                         executor.executeAsync({
                                             url: queryCandidateNotes,
                                             method: "GET",
                                             headers: { "Accept": "application/json; odata=verbose" },
                                             success: successHandler,
                                             error: errorHandler
                                         });
                                         //deferred.resolve();
                                     });
                            });
                    });

                function successHandler(data) {
                    var jsonObject2 = JSON.parse(data.body);
                    //var results2 = jsonObject2.d.results;
                    deferred2.resolve(jsonObject2);
                    //alert('2nd success:' + jsonObject2);
                    //return jsonObject2;
                }

                function errorHandler(data, errorCode, errorMessage) {
                    alert('Error2 :' + errorMessage + data.body);
                }
                // Get 
                return deferred2.promise;

};

Method 3: Calling method 2 after method 1

   var getRequest = function (query, queryCandidateNotes) {


                var deferred = $q.defer();
                $.when(getCandidates(query, queryCandidateNotes)).then(function (data) {

                    alert('Success1:' + data);

                                           $.when(getCandidateNotes(queryCandidateNotes)).then(function (data1) {
                        deferred.resolve(data);
                        alert('Success2:' + data1);
                    });
                    })
                return deferred.promise;
            };

            return {
                getRequest: getRequest

            };

        }]);
})();

Solution

  • $.when is not appropriate here, utilize $q.all that combines multiple promises into a single promise that is resolved when all of the input promises are resolved.

    Example

    app.controller('listController', function ($scope, $q, listService) {
        SP.SOD.executeFunc('SP.RequestExecutor.js', 'SP.RequestExecutor', function () {
    
            $q.all([listService.getListItems('Documents'), listService.getListItems('Site Pages')]).then(function (data) {
                $scope.documentsItems = data[0].d.results;
                $scope.sitePagesItems = data[1].d.results;
    
            });
    
        });
    });
    

    where listService is a service for getting list items:

    app.factory('listService', ['$q', function ($q) {
        var getListItems = function (listTitle) {
            var d = $q.defer();
            JSRequest.EnsureSetup();
            var hostweburl = decodeURIComponent(JSRequest.QueryString["SPHostUrl"]);
            var appweburl = decodeURIComponent(JSRequest.QueryString["SPAppWebUrl"]);
    
            var queryUrl = appweburl + "/_api/SP.AppContextSite(@target)/web/lists/getByTitle('" + listTitle + "')/items?@target='" + hostweburl + "'";
            var executor = new SP.RequestExecutor(appweburl);
            executor.executeAsync({
                url: queryUrl,
                method: "GET",
                headers: { "Accept": "application/json; odata=verbose" },
                success: function(data, textStatus, xhr) {
                    d.resolve(JSON.parse(data.body));
                },
                error: function(xhr, textStatus, errorThrown) {
                    d.reject(JSON.parse(xhr.body).error);
                }
            });
            return d.promise;
        };
    
        return {
            getListItems: getListItems
        };
    }]);
    

    Solution description

    enter image description here

    Default.aspx

    <asp:Content ContentPlaceHolderID="PlaceHolderAdditionalPageHead" runat="server">
        <script type="text/javascript" src="../Scripts/jquery-1.9.1.min.js"></script>
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
    
        <SharePoint:ScriptLink Name="sp.js" runat="server" OnDemand="true" LoadAfterUI="true" Localizable="false" />
        <meta name="WebPartPageExpansion" content="full" />
    
        <!-- Add your CSS styles to the following file -->
        <link rel="Stylesheet" type="text/css" href="../Content/App.css" />
    
        <!-- Add your JavaScript to the following file -->
    
        <script type="text/javascript" src="../Scripts/listService.js"></script>
        <script type="text/javascript" src="../Scripts/App.js"></script>
    
    </asp:Content>
    

    and

    <asp:Content ContentPlaceHolderID="PlaceHolderMain" runat="server">
        <div ng-app="SPApp" ng-controller="listController">
        </div>
    </asp:Content>
    

    App.js

    'use strict';
    
    (function() {
    
        var app = angular.module('SPApp', ['SPApp.services']);
    
        app.controller('listController', function ($scope, $q, listService) {
    
            executeOnSPLoaded(function () {
                    $q.all([listService.getListItems('Documents'), listService.getListItems('Site Pages')]).then(function (data) {
                        $scope.documentsItems = data[0].d.results;
                        $scope.sitePagesItems = data[1].d.results;
                    });
            });
    
    
        });
    
    })();
    
    
    
    function executeOnSPLoaded(loaded) {
        JSRequest.EnsureSetup();
        var hostweburl = decodeURIComponent(JSRequest.QueryString["SPHostUrl"]);
        var scriptbase = hostweburl + "/_layouts/15/";
        $.when(
            //$.getScript(scriptbase + "SP.Runtime.js"),
            $.getScript(scriptbase + "SP.js"),
            $.getScript(scriptbase + "SP.RequestExecutor.js"),
            $.Deferred(function (deferred) {
                $(deferred.resolve);
            })
        ).done(function () {
            loaded();
        });
    }
    

    listService.js

    'use strict';
    
    
    angular.module('SPApp.services',[])
    .factory('listService', ['$q', function ($q) {
        var getListItems = function (listTitle) {
            var d = $q.defer();
            JSRequest.EnsureSetup();
            var hostweburl = decodeURIComponent(JSRequest.QueryString["SPHostUrl"]);
            var appweburl = decodeURIComponent(JSRequest.QueryString["SPAppWebUrl"]);
    
            var queryUrl = appweburl + "/_api/SP.AppContextSite(@target)/web/lists/getByTitle('" + listTitle + "')/items?@target='" + hostweburl + "'";
            var executor = new SP.RequestExecutor(appweburl);
            executor.executeAsync({
                url: queryUrl,
                method: "GET",
                headers: { "Accept": "application/json; odata=verbose" },
                success: function(data, textStatus, xhr) {
                    d.resolve(JSON.parse(data.body));
                },
                error: function(xhr, textStatus, errorThrown) {
                    d.reject(JSON.parse(xhr.body).error);
                }
            });
            return d.promise;
        };
    
        return {
            getListItems: getListItems
        };
    }]);