3

I think this seems like an obvious question, but my brain seems to be a bit fried.

I have a resource

Book = $resource("/books/:id", {id: "@id"});
book = Book.get(1);

I want to refresh the object to get changes from the server. I know I can do that by repeating book = Book.get(book.id), but that would mean that everything on the page that's watching book would temporarily get nulled until the query returned and functions that operate on it might crash.

I want to add a reload method to instances that updates any changed fields once the query returns from the server. My best attempt so far is:

$reload = function() {
    var model = this;

    Book.get(model.id, function(data) { // success
      angular.forEach(data, function(value, key) {
          model[key] = value;
      }
    }
}

Two questions a) Is this the "angular" way to do it, or is there a more elegant way? a) How do I add this $refresh method when defining the resource so that it gets included on every instance created?

ChrisJ
  • 2,486
  • 21
  • 40

3 Answers3

3

Try to extent it's prototype:

var Book = $resource("/books/:id", {id: "@id"});
Book.prototype.reload = function(callback) {
    return this.get(this.id, callback);
}

var book = Book.get(1);
book.reload(function(data){console.log(data);});

thanks to: @mathew-berg (Mathew Berg) for making fixes on my code.

num8er
  • 18,604
  • 3
  • 43
  • 57
1

A couple of thoughts:

  1. How is your model structured? From the $resource docs: "Having an empty object results in no rendering, once the data arrives from the server then the object is populated with the data and the view automatically re-renders itself showing the new data."
  2. Roll your own API interaction in an Angular Service so that you can control the async behavior:

    yourApp.factory('BookService', function($q) {
    
       //Other API calls here
    
       function reload() {
          var deferred = $q.defer();
    
          $http.get('/someUrl').
          success(function(data, status, headers, config) {
             //Massage your data here... then
             deferred.resolve(data);
          }).
          error(function(data, status, headers, config) {
             deferred.reject('There was a problem updating the books');
          });
    
          return deferred.promise;
       }
    
       return {
          reload: reload
       }
    });
    
    //In your conttroller or directive that holds your model
    books = BookService.reload();
    
Nevy
  • 31
  • 5
0

@num8er's solution wouldn't even run without crashing for me. Maybe we're using different versions of angular? (I'm on 1.4.x at the moment.) In particular, I had to change get() to $get(), but I was also looking to reload the object without having pass in a custom callback to capture it from everywhere I called reload, so I added that to the inner part.

I had to do:

var Book = $resource("/books/:id", {id: "@id"});
Book.prototype.reload = function() {
    var book = this;
    book.$get(book.id, function (new_book) {
        book = new_book;  // replace old book object with newly reloaded one
    });
};

var book = Book.get(1);
book.reload();
Nathan Stocks
  • 2,096
  • 3
  • 20
  • 31