0

I have this factory:

angular.module('core.actor').factory('Actor', ['$resource',
    function ($resource) {
        return $resource('api/actor/:actorId/', {}, {
            query: {
                method: 'GET',
                isArray: true,
                cache: true
            },    
            update: {
                method: 'PUT'
            }
        });
    }
]);

And this is part of my paging function:

if (self.pk == "-6" && self.searchTerm == undefined) {
    self.actorsToAdd = Actor.query({
        offset: pageOffset,
        limit: pageLimit
    })
} else if (self.pk == "-6") {
    self.actorsToAdd = Actor.query({
        offset: pageOffset,
        limit: pageLimit,
        search: self.searchTerm
    })
} else if (self.searchTerm == undefined) {
    self.actorsToAdd = Actor.query({
        offset: pageOffset,
        limit: pageLimit,
        pk: self.pk.toString()
    })
} else {
    self.actorsToAdd = Actor.query({
        offset: pageOffset,
        limit: pageLimit,
        search: self.searchTerm,
        pk: self.pk.toString()
    })
}

It changes the GET request generated by Actor depending on certain conditions. I'm looking for a way to parametrize this function so I would be able to replace 'Actor' with a variable.

Something along the lines of:

pageType = Movie;

var page = function (pageType){

  self.itemsToAdd = pageType.query({
      offset: pageOffset,
      limit: pageLimit
  })  
}

Is it possible? If so, how?

6
  • Yes it is possible. add params and pass whole object according to your request. find docs: docs.angularjs.org/api/ngResource/service/$resource Commented Jul 20, 2016 at 11:55
  • Thanks! Could you please give me an example? I'm not clear where I should make the changes. According to the docs it seems that the params should be defined in the 'Actor' factory. Commented Jul 20, 2016 at 12:08
  • Have your factory do more than return just one $resource...think of Movies factory that returns all the resources needed ... Actor, Movie, Genre etc Commented Jul 20, 2016 at 12:34
  • @charlietfl Thanks! Again, an example would be greatly appreciated. From what I understand the factory returns a single $resource, that access a single API path. How would I go about making this factory return multiple $resources ? Commented Jul 20, 2016 at 13:50
  • Can put all the resources in one object and either return that or return function that takes resource name as argument and it returns the appropriate one from the object Commented Jul 20, 2016 at 13:53

1 Answer 1

1

This is how I do it, rather than passing individual parameters into the query, pass in a object, which contains your query parameters.

angular.module('core.actor').factory('Actor', ['$resource',
  function ($resource) {
     return $resource('api/actor/:actorId/', {}, {
       query: {
       method: 'GET',
       isArray: true,
       cache: true,
       params: { queryParams: '@_queryParams' }
    },
    update: {
      method: 'PUT'
    }
  });
}
]);

so your call to it looks like this

Actor.query({ queryParams: {
    offset: pageOffset,
    limit: pageLimit,
    pk: self.pk.toString()
}})

Then on the server I look at which values are contained in my (json parsed) params, in order to construct the appropriate query on the database.

After your latest comment, is this the kind of thing you're looking for?

angular.module('core.actor').factory('Api', ['$resource',
  function ($resource) {
    return {
      actor: $resource('api/actor/:actorId/', {}, {
        query: {
      method: 'GET',
      isArray: true,
      cache: true,
      params: {queryParams: '@_queryParams'}
    },
    update: {
      method: 'PUT'
    }
  }),
  movie: $resource('api/move/:moveId/', {}, {
    query: {
      method: 'GET',
          isArray: true,
          cache: true,
          params: {queryParams: '@_queryParams'}
        },
        update: {
          method: 'PUT'
        }
      })
    };
  }
]);

You could then call either Api.movie.query() or Api.actor.query()

For completeness, heres how my server side code looks when building my query.

var constructUserQuery = function (queryParams) {
  var query = { $or: [], $and: [] };

  if (queryParams.name) {
    query.$and.push({ displayName: { $regex: queryParams.name,     $options: 'i'} });
  }

  if (queryParams.client) {
    query.$or.push({ client: mongoose.Types.ObjectId(queryParams.client) });
  }

  if (queryParams.roles) {
    query.$or.push({ roles: { $in: queryParams.roles }});
  }

  // Ignore the current user, if it's supplied
  if (queryParams.user) {
    query.$and.push({ _id: { $ne: queryParams.user._id }});
  }

  // Clean up any empty arrays
  if (query.$or.length === 0) {
    delete query.$or;
  }

  if (query.$and.length === 0) {
    delete query.$and;
  }

  return query;
};

Obviously this is specific to my case but you get the idea. This is the only place where I have any if statements.

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

8 Comments

Yes, but how will this help me replace the 'Actor' factory with a different factory ?
You're making assumptions that all your factories accept the same parameters?
Sudgen Basically yes, the only thing that is different are the API urls
I've updated my answer with another way to do it, which I think is what charliefl was suggesting
I'll try this out and see if I'll manage to get it to work. But let me see if I understand what you are saying,You idea is skipping all the if statements in the paging function and send all the params to the server what ever they may be and let the server figure out what to return. Won't it just place the if statements on the server side?
|

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.