AngularJs ngResource for nested api resurces with different endpoints
Asked Answered
J

2

9

I have this endpoints

/clients/:id
/bills/:id
/clients/:id/bills

I'm trying to create some resources with angular-resource to represent my API.

Clients and Bills Resources

I created a resource for the clients,

.factory('Clients', function($resource){
   return $resource('/clients/:id')
})
.factory('Bills', function($resource){
   return $resource('/bills/:id')
});

Those worked fine.

The Problem

My problem is when I wanted to define a resource to represent the bills of a client calling the endpoint /client/:id/bills

I thought that this should be a Bills resource with a method getFromClient() or something like that, as it will return an array of Bills from the client. But I have already use the Bills name. And the endpoint is different to the one already defined.

Any idea how to structure this?

Jobe answered 25/3, 2013 at 20:5 Comment(2)
Why not passing two variables to the client? Something like id and bills? If you leave the last one undefined you just get everything from a certain client and if its true you only get its bills.Pepita
@Flek But if I pass variables to the Clients service is going to return Client resources instead of Bill resources (with the Clients methods)Jobe
J
18

I think what I was loooking for is now in Anguar 1.1

.factory('Bills', function($resource){
  return $resource('/bills/:id',{}, {
    get: {
      method: 'GET',
      params:{
        clientId: '@clientId'
      }
    },
    'getFromClient': {
      method:'GET',
      params: {
        clientId: '@clientId'
      },
      url: host + "/clients/:clientId/bills",
      isArray: true
     }
   })
});

Now you can add a url property to the method declaration to override the main url.

If you want to go with a library that enable you to solve this problema and many others, you could try https://github.com/platanus/angular-restmod

Here is an example:

.factory('Client', function(restmod){
    return restmod.model('clients', {
        bills: { hasMany: 'Bill' }
    });
}

.factory('Bill', function(restmod){
    return restmod.model('bills');
}

.controller('myController', function(Client){
    $scope.client = Client.$find(1);
    $scope.client.bills.$search();
});
Jobe answered 7/6, 2013 at 12:31 Comment(1)
Can you link to the documentation that explains this?Heartsome
S
5

Check the ngResource docs... Scroll down to the first example heading: http://docs.angularjs.org/api/ngResource.$resource

It's kinda confusing because they're not doing it right in the example... lol

I believe it would look something like:

.factory('Clients', function($resource){
   return $resource('/clients/:id', {id:'@id'})
})
.factory('ClientBills', function($resource){
   return $resource('/clients/:clientId/bills/:id', {clientId:'@clientId', id:'@id'})
});

I haven't tested this, but I think that's right. =)

UPDATE

You would then access them like so:

.controller('MyCtrl', function ($scope, $routeParams, Clients, Bills) {
    $scope.client = Clients.get({id:$routeParams.clientId})
    $scope.bills = ClientBills.get({clientId:$routeParams.clientId})
})

I also changed the name of the service to "ClientBills", as it is more specific to the task, and you may want a "Bills" service that doesn't require a client id...

Seaway answered 2/4, 2013 at 5:50 Comment(2)
Thanks thom and @max, I think is a good way to go if I need to go with angular 1.0Jobe
I think you'd want to call ClientBills.query(..) though, since it will be returning an array of billsSilden

© 2022 - 2024 — McMap. All rights reserved.