Controlling multiple views in one controller in AngularJS

Horen picture Horen · Jul 31, 2014 · Viewed 8.9k times · Source

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?

Answer

runTarm picture runTarm · Jul 31, 2014

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.