56

I've implemented a REST/CRUD backend by following this article as an example: http://coenraets.org/blog/2012/10/creating-a-rest-api-using-node-js-express-and-mongodb/ . I have MongoDB running locally, I'm not using MongoLabs.

I've followed the Google tutorial that uses ngResource and a Factory pattern and I have query (GET all items), get an item (GET), create an item (POST), and delete an item (DELETE) working. I'm having difficulty implementing PUT the way the backend API wants it -- a PUT to a URL that includes the id (.../foo/) and also includes the updated data.

I have this bit of code to define my services:

angular.module('realmenServices', ['ngResource']).
    factory('RealMen', function($resource){
    return $resource('http://localhost\\:3000/realmen/:entryId', {}, {
      query: {method:'GET', params:{entryId:''}, isArray:true},
      post: {method:'POST'},
      update: {method:'PUT'},
      remove: {method:'DELETE'}
    });

I call the method from this controller code:

$scope.change = function() {
    RealMen.update({entryId: $scope.entryId}, function() {
            $location.path('/');
    });
}

but when I call the update function, the URL does not include the ID value: it's only "/realmen", not "/realmen/ID".

I've tried various solutions involving adding a "RealMen.prototype.update", but still cannot get the entryId to show up on the URL. (It also looks like I'll have to build the JSON holding just the DB field values myself -- the POST operation does it for me automatically when creating a new entry, but there doesn't seem to be a data structure that only contains the field values when I'm viewing/editing a single entry).

Is there an example client app that uses all four verbs in the expected RESTful way?

I've also seen references to Restangular and another solution that overrides $save so that it can issue either a POST or PUT (http://kirkbushell.me/angular-js-using-ng-resource-in-a-more-restful-manner/). This technology seems to be changing so rapidly that there doesn't seem to be a good reference solution that folks can use as an example.

PrestoJeff
  • 561
  • 1
  • 6
  • 4
  • 1
    Thanks for linking my article :) I've found my approach is the only way I can get complete RESTful conventions to be met by Angular JS (at the moment). We've used it across a few projects. The only real issue is that the id field that represents whether it's a new or existing record isn't currently configurable, but that would be an easy update via app.config. – Oddman Aug 12 '13 at 04:07

3 Answers3

60

I'm the creator of Restangular.

You can take a look at this CRUD example to see how you can PUT/POST/GET elements without all that URL configuration and $resource configuration that you need to do. Besides it, you can then use nested resources without any configuration :).

Check out this plunkr example:

http://plnkr.co/edit/d6yDka?p=preview

You could also see the README and check the documentation here https://github.com/mgonto/restangular

If you need some feature that's not there, just create an issue. I usually add features asked within a week, as I also use this library for all my AngularJS projects :)

Hope it helps!

mgonto
  • 6,605
  • 2
  • 29
  • 36
34

Because your update uses PUT method, {entryId: $scope.entryId} is considered as data, to tell angular generate from the PUT data, you need to add params: {entryId: '@entryId'} when you define your update, which means

return $resource('http://localhost\\:3000/realmen/:entryId', {}, {
  query: {method:'GET', params:{entryId:''}, isArray:true},
  post: {method:'POST'},
  update: {method:'PUT', params: {entryId: '@entryId'}},
  remove: {method:'DELETE'}
});

Fix: Was missing a closing curly brace on the update line.

Community
  • 1
  • 1
Ye Liu
  • 8,946
  • 1
  • 38
  • 34
  • Thank you very much jaux, that's working! Now for the second part of the question, how do I get the data coming from the form fields passed as data to the PUT in the same way that it's done for POST? – PrestoJeff Jun 29 '13 at 06:04
  • That's another question on its own. Create a new specific question, include your angular and HTML code. – Ye Liu Jun 29 '13 at 06:17
  • Why does we define the entryId value with an @ sign at the beginning? "@entryID" What does this @ sign mean? What happens if I don't use that? – ankakusu May 26 '14 at 08:54
  • 4
    @ankakusu Because there is a parameter in the url `:entryId`, the `{entryId: @entryId}` is to tell angular where to find the value for that parameter. In this case, it means using the value of `entryId` property from the data as the value of `:entryId` parameter in the url. – Ye Liu May 26 '14 at 13:34
9

You can implement this way

$resource('http://localhost\\:3000/realmen/:entryId', {entryId: '@entryId'}, {
        UPDATE: {method: 'PUT', url: 'http://localhost\\:3000/realmen/:entryId' },
        ACTION: {method: 'PUT', url: 'http://localhost\\:3000/realmen/:entryId/action' }
    })

RealMen.query() //GET  /realmen/
RealMen.save({entryId: 1},{post data}) // POST /realmen/1
RealMen.delete({entryId: 1}) //DELETE /realmen/1

//any optional method
RealMen.UPDATE({entryId:1}, {post data}) // PUT /realmen/1

//query string
RealMen.query({name:'john'}) //GET /realmen?name=john

Documentation: https://docs.angularjs.org/api/ngResource/service/$resource

Hope it helps

James
  • 2,626
  • 5
  • 37
  • 51
user3618546
  • 91
  • 1
  • 1