3

Following the MVC pattern, one controller should be able to handle multiple views in AngularJS.

E.g. I have one view for showing all users and one for creating a new user. My $routeProvider (excerpt) looks like this:

app.config(['$routeProvider',
  function($routeProvider) {
    $routeProvider.
      when('/showusers', {
        templateUrl: 'partials/showusers.html',
        controller: 'userController'
      }).   
      when('/createuser', {
        templateUrl: 'partials/showusers.html',
        controller: 'userController'
      })
  }]);

Both views share several methods such as retrieving all user attributes. These shared methods are accessed through a factory.

The userController (excerpt) currently looks like this where Users is a factory:

angular.module('supportModule').
  controller('userController', function($scope, Users) {
    var init = function(){
      $scope.users = Users.getAll();
      $scope.attributes = Users.getAttributes();
    }
    init();
  })

The problem is: I don't need to request Users.getAll(); when I'm on the createuser view.

Of course, I could easily parse the route by using $location, the $routeProvider or pure JS and then conditonally call methods - but I figure there is a more elegant and efficient way in Angular :)
Something like in typical MVC frameworks where one controller has many actions - one for each view.

So my question:
How to elegantly call methods based on the view in a controller which controls more than one view?

Horen
  • 11,184
  • 11
  • 71
  • 113
  • 2
    Check [`resolve`](http://docs.angularjs.org/api/ngRoute.%24routeProvider) – okm Jul 31 '14 at 15:50
  • you can share the data between the controllers using the same factory which is sharing the methods... this way you wont have to do getAll again... – harishr Jul 31 '14 at 15:56
  • @HarishR Yes, I know that and I'm doing it. However, I would have two controllers again, so one controller for each view which is what I'm trying to avoid. – Horen Jul 31 '14 at 15:58
  • in that case the only solution i can think of is having some parent html with ng-if/ng-include/ng-controller.. ui-router is much better for handling things like these... – harishr Jul 31 '14 at 16:01

1 Answers1

5

You could use resolve: when setup $routeProvider to pass values to a controller depending on the matched route.

app.config(['$routeProvider',
  function($routeProvider) {
    $routeProvider.
      when('/showusers', {
        templateUrl: 'partials/showusers.html',
        controller: 'userController',
        resolve: {
          ctrlOptions: function () {
            return {
              getAllUsers: true,
            };
          }
        }
      }).
      when('/createuser', {
        templateUrl: 'partials/showusers.html',
        controller: 'userController',
        resolve: {
          ctrlOptions: function () {
            return {
              getAllUsers: false,
            };
          }
        }
      })
  }]);

and then in the controller, you can inject item specified in resolve: like this:

app.controller('userController', function ($scope, Users, ctrlOptions) {
  var init = function () {
    if (ctrlOptions.getAllUsers) {
      $scope.users = Users.getAll();
    }

    $scope.attributes = Users.getAttributes();
  };

  init();
});

Hope this helps.

runTarm
  • 11,537
  • 1
  • 37
  • 37
  • Thanks for your input. I haven't used `resolve` yet, but it seems to be pretty handy. For my example though, I don't see a big advantage over checking for the current route in the controller right away. – Horen Jul 31 '14 at 20:40
  • Sometimes you don't need to add resolve to every route, if you don't do so, angular will return unknown provider error. is there any way to avoid that or maybe another way to handle that case ? – badr slaoui Dec 02 '15 at 21:40