0

I want to create a find method that loops through an array returned by the $resource service in Angular.

If I have a service like so:

'use strict';

angular.module('adminApp').factory('ProductType', function($resource) {
  var ProductType;
  ProductType = $resource('http://localhost:3000/api/v1/product_types/:id.json', {
    id: '@id'
  }, {
    update: {
      method: 'PUT'
    }
  });


  ProductType.find = function(typeName){
    var types = this.query(),
        typeObject = {},
        self = this;

    for(type in types) {
       var result = types[type],
           resultName = self.normalizeName(result.name),       

       if(typeName === resultName) {
         typeObject = result;
       } 
     }

     return typeObject;
  };

  return ProductType;
});

I tried wrapping it all in a function and returning the function thinking it had something to do with it being async and I also tried nesting a callback in the query method but that just allowed me to modify the response and not actually return anything differently.

When I try and set the return value to $scope in the controller I get a blank object

1 Answer 1

1

The this.query() method would return an array which might not be filled until the this.query() method has got its results back from the server. You will need to do something like this to wait until the call to the server has completed. As this is sort of async you will need to return a promise from this method that is resolved when the initial query has completed and you have searched the results.

'use strict';

angular.module('adminApp').factory('ProductType', [
  '$q',
  '$resource',
  function($q, $resource) {
    var ProductType;
    ProductType = $resource('http://localhost:3000/api/v1/product_types/:id.json', {
      id: '@id'
    }, {
      update: {
        method: 'PUT'
      }
    });


    ProductType.find = function(typeName) {
      var defer = $q.defer(),
          types = this.query(),
          self = this;

          types.$promise.then(function () {
            var result, 
                resultName,
                typeObject,
                type;

            for(type in types) {
               result = types[type];
               resultName = self.normalizeName(result.name);    

               if(typeName === resultName) {
                 typeObject = result;
                 break;
               } 
             }

             defer.resolve(typeObject);
          }, function (err) {
            // the called failed
            defer.reject(err);
          })

       return defer.promise;
    };

    return ProductType;
  }]);

Taken from the angular docs https://docs.angularjs.org/api/ngResource/service/$resource

It is important to realize that invoking a $resource object method immediately returns an empty reference (object or array depending on isArray). Once the data is returned from the server the existing reference is populated with the actual data. This is a useful trick since usually the resource is assigned to a model which is then rendered by the view. 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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.