Recommended way of getting data from the server
Asked Answered
H

2

145

What is the recommended way to connect to server data sources in AngularJS without using $resource.

The $resource has many limitations such as:

  1. Not using proper futures
  2. Not being flexible enough
Hedve answered 7/8, 2012 at 16:14 Comment(2)
Is it still true that $resource has the limitation of not using proper futures given that this issue (https://github.com/angular/angular.js/issues/415) has been closed? (I'm new to Angular, my apologies if the question is confusing.) EDIT - This commit (github.com/angular/angular.js/commit/…) also seems to suggest that $resource may not have that limitation anymore?Thyroid
well it's legal in here to answer your own questions ..ok? press "Ask Question", that's called "share your knowledge"Criticism
H
230

There are cases when $resource may not be appropriate when talking to backend. This shows how to set up $resource like behavior without using resource.

angular.module('myApp').factory('Book', function($http) {
  // Book is a class which we can use for retrieving and 
  // updating data on the server
  var Book = function(data) {
    angular.extend(this, data);
  }

  // a static method to retrieve Book by ID
  Book.get = function(id) {
    return $http.get('/Book/' + id).then(function(response) {
      return new Book(response.data);
    });
  };

  // an instance method to create a new Book
  Book.prototype.create = function() {
    var book = this;
    return $http.post('/Book/', book).then(function(response) {
      book.id = response.data.id;
      return book;
    });
  }

  return Book;
});

Then inside your controller you can:

var AppController = function(Book) {
  // to create a Book
  var book = new Book();
  book.name = 'AngularJS in nutshell';
  book.create();

  // to retrieve a book
  var bookPromise = Book.get(123);
  bookPromise.then(function(b) {
    book = b;
  });
};
Hedve answered 7/8, 2012 at 16:14 Comment(11)
Maybe a noob question but how would one extend this to allow for a get() that returned multiple responses not just a single response?Incurable
@NathanBunney, you could have your static get method above loop through the results and build an array of Books.Cavill
@NathanBunney ' Book.getAll = function() { return $http.get('/Book').then(function(response) { var books = []; for(var i = 0; i < response.data.length; i++){books.push(new Book(response.data[i]));} return books; }); };'Warga
why do i get Unknown provider: BookProvider <- Book Error ??Codi
How would you share a book or collection of books between controllers?Deviant
@MiskoHevery Why does Book.get() call to the server only once and then when called again from the controller - it doesn't poll the server any more? I want to use it in the $timeout and have that issue...Pebble
In the controller I had to remove new Book() and just make it var book = Book. I'm not well versed enough in JS to say why.Riocard
can anybody explain me what is the purpose of return new Book(response.data); instead of return response.data;Jemadar
You seem to assume that your $http.get cannot fail?Dyadic
@Jemadar The idea is to return an object that has methods you can call on it like "update"; which wasn't shown, I assume for brevity. You can see how "update" can be implemented by looking at "create".Aruspex
This is great (obviously since Misko created the framework), but I'm struggling to figure out how to make it reusable. If I wanted to implement the CRUD functions only once and then inherit their functionality in child factories/services that needed only a urlBase argument (preferably stored on the prototype so that each instance didn't need a new copy of the urlBase), how would I do that?Cohla
L
26

I recommend that you use $resource.

It may support (url override) in next version of Angularjs. Then you will be able to code like this:

// need to register as a serviceName
$resource('/user/:userId', {userId:'@id'}, {
    'customActionName':    {
        url:'/user/someURI'
        method:'GET',
        params: {
            param1: '....',
            param2: '....',
        }
    },
     ....
});

And return callbacks can be handled in ctrl scope like this.

// ctrl scope
serviceName.customActionName ({
    paramName:'param',
    ...
}, 
function (resp) {
    //handle return callback
}, 
function (error) {
    //handler error callback
});

Probably you can handle code on higher abstraction level.

Laurentia answered 4/3, 2013 at 2:38 Comment(3)
Current version of angular.js supports url override in $resource module.Laurentia
Haha you are recommending the actual creator of the framework on how to do something :PScorekeeper
OMG! I feel so ashamed.Laurentia

© 2022 - 2024 — McMap. All rights reserved.