6

I would like to ask you if there is a possibility to use ClientContext with AngularJS?

In this way I want to take all items, sort them, filter, make some modification and etc. Later maybe I will add a new item to the List.

I already use SharePoint 2010 and AngularJS but with REST not with the ClientContext. The issue is that with REST I can take only 1000 records. For more I must provide pagination. I observe that for REST and pagination every 1000 records is almost 1-1.5 sec delay.

That's why I'm looking for a way to use ClientContext and AngularJS on SharePoint 2010. I will be really thankful if somebody can help me.


EDIT

I try many thing unfortunately without success. Here is my code:

(function(){

    var app = angular.module('store', []);//'store' = module name; []- dependencies: for now we don't have any dependencies

    app.controller('spListCtrl', function($scope, SharePointList){

        var self = this;
        self.products = SharePointList.list();
        alert('1 ' + self.products.length);

    });

    app.service('SharePointList', function(){

        var self = this;

        self.allItems = [];

        self.list = function()
        {   
            EnsureScriptFunc("sp.js", "SP.ClientContext", function () {
                                alert('2 ' + self.allItems.length);
                               var loc = new SP.ClientContext(_spPageContextInfo.webServerRelativeUrl);

                                var web = loc.get_web();
                                var locList = web.get_lists().getByTitle("AngularTest");

                                var query = new SP.CamlQuery();

                                        var queryString = "<View>\
                                                             <Query>\
                                                                <OrderBy>\
                                                                    <FieldRef Name='Title' Ascending='True'/>\
                                                                </OrderBy>\
                                                            </Query>\
                                                        </View>";
                                 query.set_viewXml(queryString);

                                 var locItems = locList.getItems(query);

                                 // Ensure the fields we want to retrieve are returned
                                 loc.load(locItems, "Include(ID,Title,Name,Adress)");

                                 // Send our query to the server for processing.
                                 loc.executeQueryAsync(function () {
                                    var beratungTrainings = [];
                                    var locItemEnumerator = locItems.getEnumerator();
                                    // Iterate through our retrieved data set and build an array of JSON objects containing
                                    // the relevent properties.
                                    while (locItemEnumerator.moveNext()) {

                                        var longBeratungObject = new createItems({
                                            Adress: locItemEnumerator.get_current().get_item("Adress"),
                                            Name: locItemEnumerator.get_current().get_item("Name"),
                                            Title: locItemEnumerator.get_current().get_item("Title"),
                                            Id: locItemEnumerator.get_current().get_item("ID")
                                        });

                                        beratungTrainings.push(longBeratungObject);

                                    }
                                        self.allItems  = beratungTrainings;
                                        alert('3 ' + self.allItems.length);
                                        return self.allItems;

                                   }, function (sender, args) {
                                      alert('Loading failed. ' + args.get_message() + '\n' + args.get_stackTrace());
                                });

                            });
        };


    });

    function createItems(data){
        var self = this;
        self.ID = data.ID;
        self.Title = data.Title;
        self.Name = data.Name;
        self.Adress = data. Adress;
    };


})();

The problem is that first I receive error: 'Cannot read property 'length' of undefined' on line in which I have alert '1'. Next I see alert '2' and after some time alert '3' and I don't see any result on my page.

I want to see first alert '2' next '3' and when he finish then he must to return alert '1' from the controller and show the result.

Any idea what I'm doing wrong?

2

Here is a provider I created to get data from sharepoint lists:

(function () {
//// SharePointListService.js
"use strict";
var module = angular.module('sharePointList', []);
module.provider('SharePointList', function () {
    var clientCtx;
    var web;
    var configuration = {};
    this.$get = ['$q',"$log", function ($q,$log) {
        var contextLoaded = $q.defer();
        SP.SOD.executeFunc('sp.js', 'SP.ClientContext', function () {
            clientCtx = SP.ClientContext.get_current();
            web = clientCtx.get_web();
            contextLoaded.resolve();
        });
        function createServiceForConfiguration(config) {
            var service = {};
            service.self = service;
            service.clientCtx = clientCtx;
            service.web = web;
            service.getListItems = function (listName, queryString, fields) {
                var deferred = $q.defer();
                contextLoaded.promise.then(function () {
                    var list = web.get_lists().getByTitle(listName);
                    var query = new SP.CamlQuery();
                    query.set_viewXml(queryString);
                    var listItems = list.getItems(query);
                    var fieldList = fields.join(",");
                    clientCtx.load(listItems,"Include("+fieldList+")" );
                    clientCtx.executeQueryAsync(function () {
                        var resultItems = [];
                        var listItemEnumerator = listItems.getEnumerator();
                        while (listItemEnumerator.moveNext()) {
                            var listItem = listItemEnumerator.get_current();
                            var resultItem = {};
                            for (i = 0; i < fields.length; i++) {
                                resultItem[fields[i]] = listItem.get_item(fields[i]);
                            }
                            resultItems.push(resultItem);
                        }
                        deferred.resolve(resultItems);
                    }, function (sender, args) {
                        var messageFormat="Loading of list {0} with  failed with error. {1} \n{2}";
                        var message=messageFormat.format(listName,args.get_message() ,args.get_stackTrace());
                        $log.error(message);
                    })
                });
                return deferred.promise;
            };
            return service;
        }
        return createServiceForConfiguration(configuration);
    }];
}
);})();

and an example of using it (with ng-grid and ui router): javascript

(function () {
"use strict";
var app = angular.module("app1", [
    // angular stuff
    "ui.router",
    "sharePointList",
    "ngGrid",
    'ngSanitize'
]);
app.config(function (SharePointListProvider, $stateProvider, $urlRouterProvider) {
    // For any unmatched url, redirect to /portfolios
    $urlRouterProvider.otherwise("/distributionGroups");
    $stateProvider
     .state('distributionGroups', {
         url: '/distributionGroups',
         templateUrl: 'distributiongroupstemplate.html',
         controller: "SharePointListCtrl"
     });
});
app.controller("SharePointListCtrl", ["$scope", "$state", "SharePointList", "$templateCache", function ($scope, $state, SharePointList, $templateCache) {
    $scope.gridOptions = {
        data: 'distributionGroups',
        enableCellSelection: true,
        enableRowSelection: false,
        enableCellEdit: true,
        columnDefs: [
            { field: 'Title', displayName: 'Title', enableCellEdit: false, width: "160px", resizeable: true },
            { field: 'EMail', displayName: 'E-Mail', width: "160px" }
        ]
    };
    var queryString = "<View><Query><OrderBy><FieldRef Name='Title' Ascending='False'/></OrderBy></Query></View>";
    SharePointList.getListItems("DistributionGroups", queryString,["Title","EMail"]).then(function (distributionGroups) {
        $scope.distributionGroups = distributionGroups;
    });
}]);})();
window.onload = function () {
    var $rootelement = angular.element(window.document);
    var modules = [
        "ng",
        "app1",
        function ($provide) { $provide.value("$rootElement", $rootelement); }
    ];
    var $injector = angular.injector(modules);
    var $compile = $injector.get("$compile");
    var compositeLinkFn = $compile($rootelement);
    var $rootScope = $injector.get("$rootScope");
    compositeLinkFn($rootScope);
    $rootScope.$apply();
};      

and html (on a site page)

<div>
         <a data-ui-sref="distributionGroups">Distribution Groups</a>
   </div>
   <div data-ui-view>default content</div>  
 </div>
<script type="text/ng-template" id="distributiongroupstemplate.html" >
    <div id="distributiongroups">
        <div class="gridStyle" data-ng-grid="gridOptions">
        </div>
    </div>
    </script>

I haven't used it with large lists, so i dont know how it will perform. Also,I haven't gotten it to do create/update/delete yet, but hope to soon.

  • How are you structuring your code? I have a list named Distribution Groups (no space), and a folder named dg within a the Style Library, with a sub-folder named js. Then i have the list service code in SharePointListService.js, and the remainder of the code in app.js. Where do I create the distributiongroupstemplate.html? how are you referencing the various code files (CEWP)? – Jason Jul 19 '14 at 16:40
  • I place the HTML in the example on a site page which is being deployed as a custom solution, but you should be able to do it in a CEWP as well. You Don't need to create a file named distributiongroupstemplate.html. when the stateprovider sees the state with templateUrl: 'distributiongroupstemplate.html' it find the tenplate in the page based on id tag of the script. You ought to be able to take the html above, put it in an html file in your style library, and then include that on a page with a CEWP. – russellg Jul 21 '14 at 17:39
  • Sweet! Have you had any luck with the create/update/delete? – Jason Jul 25 '14 at 17:31
  • I got create and delete, but still working on update(need to trak the version info). I'll post an update when done, – russellg Jul 26 '14 at 1:19
  • I posted an update to the provider I posted earlier that supports basic crud operations: – russellg Aug 6 '14 at 17:36
2

Here's an update to the provider I posted earlier that supports basic crud operations against a sharepoint 2010 (and probably 2013) List

// SharePointListService.js
(function () {
    "use strict";
    var module = angular.module('sharePointList', []);
    module.provider('SharePointList', function () {
        var clientCtx;
        var web;
        var configuration = {};
        this.$get = ['$q',"$log", function ($q,$log) {
            var contextLoaded = $q.defer();
            SP.SOD.executeFunc('sp.js', 'SP.ClientContext', function () {
                clientCtx = SP.ClientContext.get_current();
                web = clientCtx.get_web();
                contextLoaded.resolve();
            });
            function createServiceForConfiguration(config) {
                var service = {};
                service.self = service;
                service.clientCtx = clientCtx;
                service.web = web;
                service.getListItems = function (listName, queryString, fields) {
                        var deferred = $q.defer();
                    contextLoaded.promise.then(function () {
                        var list = web.get_lists().getByTitle(listName);
                        var query = new SP.CamlQuery();
                        query.set_viewXml(queryString);
                        var listItems = list.getItems(query);
                        var fieldList = fields.join(",");
                        clientCtx.load(listItems,"Include("+fieldList+")" );
                        clientCtx.executeQueryAsync(function () {
                            var resultItems = [];
                            var listItemEnumerator = listItems.getEnumerator();
                            while (listItemEnumerator.moveNext()) {
                                var listItem = listItemEnumerator.get_current();
                                var resultItem = {};
                                for (i = 0; i < fields.length; i++) {
                                    resultItem[fields[i]] = listItem.get_item(fields[i]);
                                }
                                resultItems.push(resultItem);
                            }
                            deferred.resolve(resultItems);
                        }, function (sender, args) {
                            var messageFormat="Loading of list {0} with  failed with error. {1} \n{2}";
                            var message=messageFormat.format(listName,args.get_message() ,args.get_stackTrace());
                            $log.error(message);
                        })
                    });
                    return deferred.promise;
                };
                service.createListItem = function (listName, item,fields) {
                    var deferred = $q.defer();
                    contextLoaded.promise.then(function () {
                        var oList = web.get_lists().getByTitle(listName);
                        var itemCreateInfo = new SP.ListItemCreationInformation();
                        this.oListItem = oList.addItem(itemCreateInfo);
                        for (var property in item)
                        {
                            var includeField;
                            if (!fields)
                            {
                                includeField = true;
                            }
                            else {
                                includeField = false;
                                for (var i = 0; i<fields.length; i++){
                                    if (fields[i]===property){
                                        includeField=true;
                                        break;
                                    }
                                }
                            }
                            if (item.hasOwnProperty(property) && includeField) {
                                oListItem.set_item(property, item[property]);
                            }
                        }
                        oListItem.update();
                        clientCtx.load(oListItem);
                        clientCtx.executeQueryAsync(function () {
                            deferred.resolve(oListItem.get_fieldValues());
                        }, function (sender, args) {
                            var messageFormat = "Loading of list {0} with  failed with error. {1} \n{2}";
                            var message = messageFormat.format(listName, args.get_message(), args.get_stackTrace());
                            $log.error(message);
                        })
                    });
                    return deferred.promise;
                };
                service.deleteListItem = function (listName, itemId) {
                    var deferred = $q.defer();
                    contextLoaded.promise.then(function () {
                        var oList = web.get_lists().getByTitle(listName);
                        this.oListItem = oList.getItemById(itemId);
                        oListItem.deleteObject();
                        clientCtx.executeQueryAsync(function () {
                            deferred.resolve();
                        }, function (sender, args) {
                            var messageFormat = "deleting item {0} from  list {1} with  failed with error. {2} \n{3}";
                            var message = messageFormat.format(itemId, listName, args.get_message(), args.get_stackTrace());
                            $log.error(message);
                        })
                    });
                    return deferred.promise;
                };
                service.saveListItem = function (listName, item, fields) {
                    var deferred = $q.defer();
                    contextLoaded.promise.then(function () {
                        var oList = web.get_lists().getByTitle(listName);
                        var oListItem = oList.getItemById(item.ID);
                        for (var property in item) {
                            var includeField;
                            if (!fields) {
                                includeField = true;
                            }
                            else {
                                includeField = false;
                                for (var i = 0; i < fields.length; i++) {
                                    if (fields[i] === property) {
                                        includeField = true;
                                        break;
                                    }
                                }
                            }
                            if (item.hasOwnProperty(property) && includeField && property != "ID") {
                                oListItem.set_item(property, item[property]);
                            }
                        }
                        oListItem.update();
                        clientCtx.load(oListItem);
                        clientCtx.executeQueryAsync(function () {
                            deferred.resolve(oListItem.get_fieldValues());
                        }, function (sender, args) {
                            var messageFormat = "update of list {0} with  failed with error. {1} \n{2}";
                            var message = messageFormat.format(listName, args.get_message(), args.get_stackTrace());
                            $log.error(message);
                        })
                    });
                    return deferred.promise;
                };
                return service;
            }
            return createServiceForConfiguration(configuration);
        }];
    }
    );
})();
0

I haven't used angularjs, so I just used an example . The problem is probably you don't handle the fact it's async.

<div ng-app='demo' ng-controller='DemoCtrl'>
    <input type="button" ng-click="makeAsyncCall()" value="DoJSON" /><br/>
    Result : {{foo}} </div>


<script type="text/javascript"> 



demo = angular.module('demo', [], '');

demo.controller('DemoCtrl',

function ($scope, DemoService) {

    $scope.$on('asyncResult', function (event, data) {
        $scope.foo = data;
    });

    $scope.makeAsyncCall = function() {        
        DemoService.makeAsyncCall($scope);
    };

});

demo.factory('DemoService', function ($http, $rootScope) {
    var service = {
        makeAsyncCall: function (theScope) {
            console.log('making a call...');

        SP.SOD.executeFunc('sp.js', 'SP.ClientContext', function () {
            var clientContext = SP.ClientContext.get_current();
            var web = clientContext.get_web();
            clientContext.load(web, "Id");


             clientContext.executeQueryAsync(function () {
                 theScope.$broadcast('asyncResult', web.get_id());
             },
             function() {
                theScope.$broadcast('asyncResult', 'it failed');
             });

        });

            console.log('done');
        }
    };
    return service;
});

</script>
0

Thank you @AndersAune.

I really like your solution because there is separation of controller and factory(services).

I made some little modification.

<div ng-app='demo'>
    <div ng-controller='DemoCtrl as test'>

        <div ng-repeat="car in cars">
            {{car.Name}}
        </div>

        <input type="button" ng-click="makeAsyncCall()" value="DoJSON" /><br/>
    </div>
</div>

(function(){

    demo = angular.module('demo', [], '');

    demo.controller('DemoCtrl', function ($scope, DemoService) {

        $scope.$on('asyncResult', function (event, data) {
            console.log('finish');
            $scope.cars = data;
        });

        $scope.makeAsyncCall = function() {        
            DemoService.makeAsyncCall($scope);
        };

    });

    demo.factory('DemoService', function ($http, $rootScope) {
        var service = {
            makeAsyncCall: function (theScope) {
                console.log('making a call...');

            SP.SOD.executeFunc('sp.js', 'SP.ClientContext', function () {
                var clientContext = new SP.ClientContext(_spPageContextInfo.webServerRelativeUrl);
                var web = clientContext.get_web();
                var locList = web.get_lists().getByTitle("AngularTest");

                var query = new SP.CamlQuery();

                    var queryString = "<View>\
                                         <Query>\
                                            <OrderBy>\
                                                <FieldRef Name='Title' Ascending='True'/>\
                                            </OrderBy>\
                                        </Query>\
                                    </View>";
                 query.set_viewXml(queryString);

                 var locItems = locList.getItems(query);

                 // Ensure the fields we want to retrieve are returned
                 clientContext.load(locItems, "Include(ID,Title,Name,Adress)");

                 // Send our query to the server for processing.
                 clientContext.executeQueryAsync(function () {
                    var beratungTrainings = [];
                    var locItemEnumerator = locItems.getEnumerator();
                    // Iterate through our retrieved data set and build an array of JSON objects containing
                    // the relevent properties.
                    while (locItemEnumerator.moveNext()) {

                        var longBeratungObject = new createItems({
                            Adress: locItemEnumerator.get_current().get_item("Adress"),
                            Name: locItemEnumerator.get_current().get_item("Name"),
                            Title: locItemEnumerator.get_current().get_item("Title"),
                            Id: locItemEnumerator.get_current().get_item("ID")
                        });

                        beratungTrainings.push(longBeratungObject);

                    }
                        theScope.$broadcast('asyncResult', beratungTrainings);

                   }, function (sender, args) {
                      theScope.$broadcast('asyncResult', 'it failed');
                });

            });

                console.log('done');
            }
        };
        return service;
    });

    function createItems(data){
        var self = this;
        self.ID = data.ID;
        self.Title= data.Title;
        self.Name = data.Name;
        self.Adress = data.Adress;
    };
})();

I retrieve the console.log 'finish', but unfortunately I didn't see any result on the html page.

If I write a alert($scope.cars[0].Name) after the $scope.cars = data I receive the right answer. But not in the HTML.

I already find a solution but I have everything in the controller. I'll share it after 30 min.

It will be wonderful if there will be possibility to add separate controller and service.


After 30 min

Like I wrote before I already find a solution of my problem.

Unfortunately in my solution everything is happening in controller. I don't have separate controller and $services/$factory.

I'm using promise

Here is my solution: JavaScript

(function(){

    var app = angular.module('app', []);//'store' = module name; []- dependencies: for now we don't have any dependencies

    app.controller('defaultCtrl', function($Name, $q){

            $scope.loadingPop = true;

        SP.SOD.executeFunc('sp.js', 'SP.ClientContext', function () {
             getListData().then(function(result){
                    console.log('done...');
                                    $scope.loadingPop = false;
                    $scope.cars = result;
                });

        });

        function getListData(){

            var deferred = $q.defer();

            var arrayL = [];

            var loc =  new SP.ClientContext(_spPageContextInfo.webServerRelativeUrl);

            var web = loc.get_web();
            var locList = web.get_lists().getByTitle("AngularTest");

            var query = new SP.CamlQuery();

                    var queryString = "<View>\
                                         <Query>\
                                            <OrderBy>\
                                                <FieldRef Name='Title' Ascending='True'/>\
                                            </OrderBy>\
                                        </Query>\
                                    </View>";
             query.set_viewXml(queryString);

             var locItems = locList.getItems(query);

             // Ensure the fields we want to retrieve are returned
             loc.load(locItems, "Include(ID,Title,Name,Address)");

             // Send our query to the server for processing.
             loc.executeQueryAsync(function () {
                var allElements = [];
                var locItemEnumerator = locItems.getEnumerator();
                // Iterate through our retrieved data set and build an array of JSON objects containing
                // the relevent properties.
                while (locItemEnumerator.moveNext()) {

                    var elementObject = new createItems({
                        Address: locItemEnumerator.get_current().get_item("Address"),
                        Name: locItemEnumerator.get_current().get_item("Name"),
                        Title: locItemEnumerator.get_current().get_item("Title"),
                        Id: locItemEnumerator.get_current().get_item("ID")
                    });

                    allElements.push(elementObject);

                }

                deferred.resolve(allElements);

             }, function (sender, args) {
                alert('Loading failed. ' + args.get_message() + '\n' + args.get_stackTrace());
             });

            return deferred.promise;

        };

    });

    function createItems(data){
        var self = this;
        self.ID = data.ID;
        self.Title = data.Title;
        self.Name = data.Name;
        self.Address = data.Address;
    };

})();

and HTML

 <h1>
        Angular App</h1>
    <div ng-app="app" class="angularApp">
        <div class="angularContainer" ng-controller="defaultCtrl as main">
            <table>
                <thead>
                    <tr>
                        <td class="cell-1">
                            ID
                        </td>
                        <td class="cell-2">
                            Title
                        </td>
                        <td class="cell-3">
                            Name
                        </td>
                        <td class="cell-4">
                            Adress
                        </td>
                    </tr>
                </thead>
                <tbody>
                    <tr ng-repeat="car in cars" ng-class="{even: $even, odd: $odd}">
                        <td class="cell-1">
                            {{car.ID}}
                        </td>
                        <td class="cell-2">
                            {{car.Title}}
                        </td>
                        <td class="cell-3">
                            {{car.Name}}
                        </td>
                        <td class="cell-4">
                            {{car.Adress}}
                        </td>

                    </tr>
                </tbody>
            </table>
            <div class="loadingPop" ng-show="loadingPop">
                <div class="loading-content">
                    <img src="../img/loading.GIF"/>
                    <span>Loading...</span>
                </div>
            </div>  
        </div>
    </div>

Unfortunately even with Client Context there is a small freeze before result showing and it take around 5sec to parse 3000 items from the list.

  • Try doing it in two passes, then, grab 30 records (or however many are on your screen, then grab the remainder, getting that much data is going to take time, so the smaller the payload received the faster it will be, make sure you list the columns you want returned in viewfields else you will get much larger payloads. – BinaryJam Sep 2 '14 at 9:51
0

Works like a charm!!!

I've taken russellg's provider solution and updated it to use current versions of angular js, ui-router, and ng-grid (currently called ui-grid). Jason's "Uncaught Error: [$injector:modulerr]" error might have been due to a version mismatch.

Here's the view html. As russelg suggested, paste this html into a text file and upload to a library, drop a CEWP on the page and link to the file. Adjust the script and CSS tags to point to the proper locations on your system.

            <link rel="stylesheet" type="text/css" href="../SiteAssets/app/styles/ui-grid-stable.min.css" />
            <link rel="stylesheet" type="text/css" href="../SiteAssets/app/styles/styles.css" />
            <script type="text/javascript" src="../SiteAssets/app/scripts/angular.min.js"></script>
            <script type="text/javascript" src="../SiteAssets/app/scripts/angular-route.min.js"></script>
            <script type="text/javascript" src="../SiteAssets/app/scripts/angular-ui-router.min.js"></script>
            <script type="text/javascript" src="../SiteAssets/app/services/SharePointListService.js"></script>
            <script type="text/javascript" src="../SiteAssets/app/scripts/ui-grid-stable.min.js"></script>
            <script type="text/javascript" src="../SiteAssets/app/scripts/angular-sanitize.min.js"></script>

            <script type="text/javascript" src="../SiteAssets/app/app.js"></script>

            <div>
                <a ui-sref="distributionGroups">Distribution Groups</a>
            </div>
            <div ui-view>default content</div>  
            </div>
            <script type="text/ng-template" id="distributiongroupstemplate.html" >
                <div id="distributiongroups">
                    <div class="gridStyle" ui-grid="gridOptions">
                    </div>
                </div>
            </script>

Here's the code for app.js:

            (function () {
                "use strict";
                var app = angular.module("app1", [
                    // angular stuff
                    "ui.router",
                    "sharePointList",
                    "ui.grid",
                    "ngSanitize"
                ]);
                app.config(function (SharePointListProvider, $stateProvider, $urlRouterProvider) {
                    // For any unmatched url, redirect to /portfolios
                    $urlRouterProvider.otherwise("/distributionGroups");
                    $stateProvider
                        .state('distributionGroups', {
                        url: '/distributionGroups',
                        templateUrl: 'distributiongroupstemplate.html',
                        controller: "SharePointListCtrl"
                    });
                });
                app.controller("SharePointListCtrl", ["$scope", "$state", "SharePointList", "$templateCache", function ($scope, $state, SharePointList, $templateCache) {
                    $scope.gridOptions = {
                        data: 'distributionGroups',
                        enableCellSelection: true,
                        enableRowSelection: false,
                        enableCellEdit: true,
                        columnDefs: [
                            { field: 'Title', displayName: 'Title', enableCellEdit: false, cellClass: "w160", resizeable: true },
                            { field: 'EMail', displayName: 'E-Mail', cellClass: "w160" }
                        ]
                    };
                    var queryString = "<View><Query><OrderBy><FieldRef Name='Title' Ascending='False'/></OrderBy></Query></View>";
                    SharePointList.getListItems("DistributionGroups", queryString,["Title","EMail"]).then(function (distributionGroups) {
                        $scope.distributionGroups = distributionGroups;
                    });
                }]);})();
            window.onload = function () {
                var $rootelement = angular.element(window.document);
                var modules = [
                    "ng",
                    "app1",
                    function ($provide) { $provide.value("$rootElement", $rootelement); }
                ];
                var $injector = angular.injector(modules);
                var $compile = $injector.get("$compile");
                var compositeLinkFn = $compile($rootelement);
                var $rootScope = $injector.get("$rootScope");
                compositeLinkFn($rootScope);
                $rootScope.$apply();
            };  

And finally, russelg's SharePointListProvider with a small correction to get rid of an error due to an undeclared iterator variable:

            // russelg's awesome SharePointListService.js. See original posting at https://sharepoint.stackexchange.com/questions/101226/retrieve-all-list-items-with-angularjs-and-clientcontext/
            (function () {
                "use strict";
                var module = angular.module('sharePointList', []);
                module.provider('SharePointList', function () {
                    var clientCtx;
                    var web;
                    var configuration = {};
                    this.$get = ['$q',"$log", function ($q,$log) {
                        var contextLoaded = $q.defer();
                        SP.SOD.executeFunc('sp.js', 'SP.ClientContext', function () {
                            clientCtx = SP.ClientContext.get_current();
                            web = clientCtx.get_web();
                            contextLoaded.resolve();
                        });
                        function createServiceForConfiguration(config) {
                            var service = {};
                            service.self = service;
                            service.clientCtx = clientCtx;
                            service.web = web;
                            service.getListItems = function (listName, queryString, fields) {
                                var deferred = $q.defer();
                                contextLoaded.promise.then(function () {
                                    var list = web.get_lists().getByTitle(listName);
                                    var query = new SP.CamlQuery();
                                    query.set_viewXml(queryString);
                                    var listItems = list.getItems(query);
                                    var fieldList = fields.join(",");
                                    clientCtx.load(listItems,"Include("+fieldList+")" );
                                    clientCtx.executeQueryAsync(function () {
                                        var resultItems = [];
                                        var listItemEnumerator = listItems.getEnumerator();
                                        while (listItemEnumerator.moveNext()) {
                                            var listItem = listItemEnumerator.get_current();
                                            var resultItem = {};
                                            for (var i = 0; i < fields.length; i++) {
                                                resultItem[fields[i]] = listItem.get_item(fields[i]);
                                            }
                                            resultItems.push(resultItem);
                                        }
                                        deferred.resolve(resultItems);
                                    }, function (sender, args) {
                                        var messageFormat="Loading of list {0} with  failed with error. {1} \n{2}";
                                        var message=messageFormat.format(listName,args.get_message() ,args.get_stackTrace());
                                        $log.error(message);
                                    })
                                });
                                return deferred.promise;
                            };
                            service.createListItem = function (listName, item,fields) {
                                var deferred = $q.defer();
                                contextLoaded.promise.then(function () {
                                    var oList = web.get_lists().getByTitle(listName);
                                    var itemCreateInfo = new SP.ListItemCreationInformation();
                                    this.oListItem = oList.addItem(itemCreateInfo);
                                    for (var property in item)
                                    {
                                        var includeField;
                                        if (!fields)
                                        {
                                            includeField = true;
                                        }
                                        else {
                                            includeField = false;
                                            for (var j = 0; j<fields.length; j++){
                                                if (fields[j]===property){
                                                    includeField=true;
                                                    break;
                                                }
                                            }
                                        }
                                        if (item.hasOwnProperty(property) && includeField) {
                                            oListItem.set_item(property, item[property]);
                                        }
                                    }
                                    oListItem.update();
                                    clientCtx.load(oListItem);
                                    clientCtx.executeQueryAsync(function () {
                                        deferred.resolve(oListItem.get_fieldValues());
                                    }, function (sender, args) {
                                        var messageFormat = "Loading of list {0} with  failed with error. {1} \n{2}";
                                        var message = messageFormat.format(listName, args.get_message(), args.get_stackTrace());
                                        $log.error(message);
                                    })
                                });
                                return deferred.promise;
                            };
                            service.deleteListItem = function (listName, itemId) {
                                var deferred = $q.defer();
                                contextLoaded.promise.then(function () {
                                    var oList = web.get_lists().getByTitle(listName);
                                    this.oListItem = oList.getItemById(itemId);
                                    oListItem.deleteObject();
                                    clientCtx.executeQueryAsync(function () {
                                        deferred.resolve();
                                    }, function (sender, args) {
                                        var messageFormat = "deleting item {0} from  list {1} with  failed with error. {2} \n{3}";
                                        var message = messageFormat.format(itemId, listName, args.get_message(), args.get_stackTrace());
                                        $log.error(message);
                                    })
                                });
                                return deferred.promise;
                            };
                            service.saveListItem = function (listName, item, fields) {
                                var deferred = $q.defer();
                                contextLoaded.promise.then(function () {
                                    var oList = web.get_lists().getByTitle(listName);
                                    var oListItem = oList.getItemById(item.ID);
                                    for (var property in item) {
                                        var includeField;
                                        if (!fields) {
                                            includeField = true;
                                        }
                                        else {
                                            includeField = false;
                                            for (var k = 0; k < fields.length; k++) {
                                                if (fields[k] === property) {
                                                    includeField = true;
                                                    break;
                                                }
                                            }
                                        }
                                        if (item.hasOwnProperty(property) && includeField && property != "ID") {
                                            oListItem.set_item(property, item[property]);
                                        }
                                    }
                                    oListItem.update();
                                    clientCtx.load(oListItem);
                                    clientCtx.executeQueryAsync(function () {
                                        deferred.resolve(oListItem.get_fieldValues());
                                    }, function (sender, args) {
                                        var messageFormat = "update of list {0} with  failed with error. {1} \n{2}";
                                        var message = messageFormat.format(listName, args.get_message(), args.get_stackTrace());
                                        $log.error(message);
                                    })
                                });
                                return deferred.promise;
                            };
                            return service;
                        }
                        return createServiceForConfiguration(configuration);
                    }];
                }
                               );
            })();

I'm going to be exploring the create-update-delete functions and plan to prepare documentation for using this very awesome SharePoint list provider. Thanks russelg!!!!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.