SharePoint 2013/online – CRUD operations using AngularJS and REST
I’ve been developing some apps using AngularJS and REST.
Doing some Googleing I noticed that most developers use jQuery Ajax to make REST requests, however if you do that, you will miss out on some awesome AngularJS features.
First of all, you should check out this post on how to refresh the form digest value. You need the digest value to do CRUD operations or SharePoint will deny your requests.
Let’s create a SharePoint list with some custom fields. Note that the field internal names will be different from the display names, just to make the development easier.
SharePoint content
Custom list:
- Bookshelf
Content type:
- Book
Fields:
- Title
- Type: Single line of text
- Internal name: Title
- Summary
- Type: Multiple lines of text
- Internal name: Booksummary
- Release date
- Type: Date and Time
- Internal name: Bookreleasedate
- Is read
- Type: Yes/No
- Internal name: Bookisread
- Book author
- Type: Person or Group
- Internal name: Bookauthor
- Bookstore
- Type: Hyperlink or Picture
- Internal name: Bookstore
- Book type
- Type: Choice
- Internal name: Booktype
The service
This is a service that will handle all operations, and since it’s a AngularJS service it will be instanced and the header config will be the same for all requests.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
myApp.service('bookService', ['$http', '$q', function ($http, $q) { //Define the http headers $http.defaults.headers.common.Accept = "application/json;odata=verbose"; $http.defaults.headers.post['Content-Type'] = 'application/json;odata=verbose'; $http.defaults.headers.post['X-Requested-With'] = 'XMLHttpRequest'; $http.defaults.headers.post['If-Match'] = "*"; //Get the books this.getBooks = function(listTitle){ var dfd = $q.defer(); $http.defaults.headers.post['X-HTTP-Method'] = "" var query = "?$select=ID,Title,Booksummary,Bookreleasedate,Bookisread,Booktype,Bookstore,Bookauthor/Title,Bookauthor/UserName&$expand=Bookauthor&$orderby=Created desc"; var restUrl = "/sites/dev/_api/web/lists/getbytitle('" + listTitle + "')/items" + query; $http.get(restUrl).success(function (data) { dfd.resolve(data.d.results); }).error(function (data) { dfd.reject("error getting books"); }); return dfd.promise; } //Create a book this.addBook = function (listTitle) { var dfd = $q.defer(); $http.defaults.headers.post['X-HTTP-Method'] = ""; var restUrl = "/sites/dev/_api/web/lists/getbytitle('" + listTitle + "')/items"; $http.post(restUrl, { __metadata: { type: "SP.Data." + listTitle + "ListItem" }, Title: "New title" }).success(function (data) { //resolve the new data dfd.resolve(data.d); }).error(function (data) { dfd.reject("failed to add book"); }); return dfd.promise; } //Update a book this.updateBook = function(listTitle, book){ var dfd = $q.defer(); $http.defaults.headers.post['X-HTTP-Method'] = "MERGE"; var restUrl = "/sites/dev/_api/web/lists/getbytitle('" + listTitle + "')/items(" + book.id + ")"; $http.post(restUrl, { __metadata: { type: "SP.Data." + listTitle + "ListItem" }, Title: book.title, Booksummary: book.summary, //A lookupfield must be updated with the ID. //Add "Id" to the end of the field internal name. BookauthorId: book.author.id, Bookreleasedate: book.releaseDate, Bookisread: book.isRead, Booktype: book.type, Bookstore: { __metadata: { type: 'SP.FieldUrlValue' }, Description: book.store.descr, Url: book.store.href }, }).success(function (data) { //resolve something dfd.resolve(true); }).error(function (data) { dfd.reject("error updating book"); }); return dfd.promise; } //Delete a book this.deleteBook = function(listTitle, book){ var dfd = $q.defer(); $http.defaults.headers.post['X-HTTP-Method'] = "DELETE"; var restUrl = "/sites/dev/_api/web/lists/getbytitle('" + listTitle + "')/items("+ book.id +")"; $http.post(restUrl) .success(function (data) { //resolve something dfd.resolve(true); }).error( function (data) { dfd.reject("error deleting book"); }); return dfd.promise; } }]); |
So there are your CRUD operations. Remember that AngularJS will do the serialization of the JSON objects.
One of the biggest benefits of using $q and $http instead of jQuery Ajax and jQuery deferred is that AngularJS knows that the request was asynchronous and you don’t have to use $scope.$apply().
Here are two simple model examples
Model examples
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
//example populating books model bookService.getBooks("Bookshelf").then(function (result) { $scope.books = []; angular.forEach(result, function (b) { //Create the book from the request JSON result. var book = { id: b.ID, title: b.Title, summary: b.Booksummary, author: { fullName: b.Bookauthor.title, userName: b.Bookauthor.UserName, id: b.Bookauthor.ID }, releaseDate: b.Bookreleasedate, isRead: b.Bookisread, type: b.Booktype, store: { href: b.Bookstore.Url, descr: b.Bookstore.Description }, } $scope.books.push(book); }); }); //example add book bookService.addBook("Bookshelf").then(function (b) { var book = { id: b.ID, title: b.Title } $scope.books.push(book); }); |