Mark Fee
Mark Fee

Reputation: 122

How should I inject a CurrentUser into a controller

I'm very new to angular and trying to create a controller that will get all of the Snods that belong to the current user. I have included my CurrentUserController for reference but my question is really about the SnodController, is the way I have injected the CurrentUser and nested the calls correct, because although it works it looks wrong to me.

Apologies if this is a matter for debate and against the rules, but I wanted to get an indication as to whether I was heading in the right direction with my approach.

var apiService = angular.module("apiService", ['ngResource']);
apiService.factory('CurrentUser', function($resource) {
    return $resource(   "http://snodbert/api/v1/users/current/",   {});
});

apiService.factory('Snod', function($resource) {
    return $resource
    (   "http://snodbert/api/v1/snods/:filter/:filterid",   {}
        ,   {   'update': { method:'PUT' }
        }
    );
});

function CurrentUserController($scope, CurrentUser) {
    var user = CurrentUser.get(function() {
            $scope.user=user;
        }
    );
}

function SnodController($scope, Snod, CurrentUser) {
    var user = CurrentUser.get(function() {
        var items = Snod.get( {filter:'owner', filterid: user.id},
        function() {
            $scope.items=items.data;
        });
    });
}

Upvotes: 1

Views: 170

Answers (1)

Hitmands
Hitmands

Reputation: 14189

you're code of course is working but, just for code-style isn't elegant because is built in a way that always requires to nest a callback into another one...

In order to solve this, you can have a look on how Promises work and how their are implemented in AngularJS:

  1. ES6 PROMISES
  2. $q
  3. Promises in ngResource

So, after reading these pages you should have more clear ideas in how to solve the annoying question of Pyramid of doom.

Let's go to perform a quickly rework of your base code:

// old
apiService.factory('CurrentUser', function($resource) {
    return $resource(   "http://snodbert/api/v1/users/current/",   {});
});

// new
function CurrentUserServiceFactory($resource, $q) {
  var resource = $resource("http://snodbert/api/v1/users/current/", {});
  var self = this;
  
  self.get = function() {
    return resource
      .get()
      .$promise
    ;
  }
}
apiService.service('CurrentUserService', CurrentUserServiceFactory);
and, in your controller you can do:

function SnodController($scope, Snod, CurrentUserService) {
  CurrentUserService
    .get()
    .then(function(userResult) {
      return Snod.get({}).$promise;
    })
    .then(function(snodResult) {
      console.log(snodResult);
    })
  ;
}

Another great thing could be re-organize your code trying to understand which dependencies your controller has... For me, for example, the value of CurrentUser is a dependency and it should be placed in a route-resolve (resolves are explained here).

Using resolve you can do this directly:

function SnodController($scope, Snod, CurrentUser) {
  Snod
    .get({userId: CurrentUser.id})
    .$promise
    .then(function(snodResult) {
      console.log(snodResult);
    })
  ;
  
}

Hope it helps!

Upvotes: 1

Related Questions