2

I have a RESTful API that provides me with employees and departments. In my AngularJS app, I need to know the employee and the departments the employee belongs to. I have defined two factory services for that:

angular.module('myApp.services', [])
    .factory('Employee', function ($resource) {
        return $resource ('/api/employees/:id', { id: '@id' });
    })
    .factory('Department', function ($resource) {
        return $resource ('/api/departments/:id', { id: '@id' });
    })
;

In the controller, I call:

$scope.employee = Employee.get({id: 'me'});

Next, I want to call:

$scope.departments = [];
angular.forEach($scope.employee.departmentIds, function (departmentId) {
    $scope.departments.push(Department.get({ id: departmentId }));
});

But $scope.employee is a promise object, so $scope.employee.departmentIds will only be known when the first request is completed.

I could solve it like this:

Employee.get({id: 'me'}).$promise.then(function (employee) {
    $scope.employee = employee;
    $scope.departments = [];
    angular.forEach(employee.departmentIds, function (departmentId) {
        $scope.departments.push(Department.get({ id: departmentId }));
    });
});

The problem is that I need this information in multiple controllers, and don't want to repeat this code in every controller. So my question is: is there a way to combine these two resources as a service which provides both the employee data and the data of the departments to which that employee belongs?

2 Answers 2

2

You can do something like that:

angular.module('myApp.services', [])
    .factory('SimpleEmployee', function ($resource) {
        return $resource ('/api/employees/:id', { id: '@id' });
    })
    .factory('Department', function ($resource) {
        return $resource ('/api/departments/:id', { id: '@id' });
    })
    .factory('Employee', ['SimpleEmployee', 'Department', function(SimpleEmployee, Department) {
        return {
            get: function(params) {
                var data = SimpleEmployee.get({id: params.id}, function (employee) {
                    var obj = {
                        employee: employee,
                        departments: []
                    };                        
                    angular.forEach(employee.departmentIds, function (departmentId) {
                        obj.departments.push(Department.get({ id: departmentId }));
                    });
                    return obj;
                });
                return data;
            }
        }
    }]);

And you dont need to change anything in your controller.

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

6 Comments

Doesn't seem to work. It only contains the SimpleEmployee object, not the Department objects.
@Korneel Sorry. I copy and paste your resource code and dont see your error. You was calling Department.get({ departmentId: departmentId }) but defined the resource as $resource ('/api/departments/:id', { id: '@id' });. Edited
You should also change var data = Employee... to var data = SimpleEmployee..., but that's not the problem. The Departments resources get fetched correctly, but the object on the scope doesn't contain the departments objects, only the SimpleEmployee object. I guess I'm missing something obvious.
Well, it actually does work, but I have to do it like this: Employee.get({ id: 'me' }).then(function (data) { $scope.employee = data.employee; $scope.departments = data.departments; }. Is there a way to provide the data to the scope without using the then callback?
Okay thanks, I tested that, but that doesn't solve the problem.
|
1

This answer is based on the answer of @Beterraba (but the code example in that answer is incorrect):

Service:

angular.module('myApp.services', [])
    .factory('SimpleEmployee', function ($resource) {
        return $resource ('/api/employees/:id', { id: '@id' });
    })
    .factory('Department', function ($resource) {
        return $resource ('/api/departments/:id', { id: '@id' });
    })
    .factory('Employee', ['SimpleEmployee', 'Department', function(SimpleEmployee, Department) {
        return {
            get: function(params) {
                return SimpleEmployee.get({id: params.id}).$promise.then(function (employee) {
                    employee.departments = [];
                    angular.forEach(employee.departmentIds, function (departmentId) {
                        employee.departments.push(Department.get({ id: departmentId }));
                    });
                    delete employee.departmentIds;
                    return employee;
                });
            }
        }
    }]);

Controller:

Employee.get({ id: 'me' }).then(function (employee) {
    $scope.employee = employee;
});

From AngularJS 1.2 RC3 on you need to unwrap any promise objects on the controller. I found this information here.

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.