dinodsaurus
dinodsaurus

Reputation: 5095

Is it good to have main controller in Angular?

I dont know if this is a good practice... I have a controller defined in route config but because my HomeCtrl is in ng-if statement he cannot listen for loginSuccess so I made MainCtrl which listens for loginSuccess and reacts appropriately. This code works just fine but this smells like a hack to me. Should I remove MainCtrl and make it a service? If so some example would be really great.

Index.html

<body ng-app="myApp" ng-controller="MainCtrl">
    <div ng-if="!isLoged()">
      <signIn></signIn>
    </div>
    <div ng-if="isLoged()">
      <div class="header">
          <div class="nav">
            <ul>
                <a href="/"><li class="book">navItem</li></a>
            </ul>
          </div>
      </div>
      <div class="container" ng-view=""></div>
    </div>
</body>

App.js

    angular.module('myApp', [])
      .config(function ($routeProvider) {
        $routeProvider
          .when('/', {
            templateUrl: 'views/main.html',
            controller: 'HomeCtrl'
          })
          .otherwise({
            redirectTo: '/'
          });
      })
  .controller('MainCtrl', function ($scope) {
    $scope.user = false;
    $scope.isLoged = function(){
         if($scope.user){
          return true;
         }else{
          return false;
         }
    }
    $scope.$on('event:loginSuccess', function(ev, user) {
       $scope.user = user;
       $scope.$apply();
    });
  })
  .controller('HomeCtrl', function ($scope, $location) {
  //this is home controller  
  })
  .directive('signIn', function () {
    return {
      restrict: 'E',
      link: function (scope, element, attrs) {
        //go to the server and then call signinCallback();
      }
    };
  })
  .run(['$window','$rootScope','$log',function($window, $rootScope){
    $window.signinCallback = function (res) {
      if(res){
        $rootScope.$broadcast('event:loginSuccess', res);
      }
      else{
        $rootScope.$broadcast('loginFailure',res);
      }
    }; 
  }]);

Upvotes: 20

Views: 14608

Answers (2)

m59
m59

Reputation: 43785

I start all of my Angular projects with:

<html ng-app="appName" ng-controller="appNameCtrl">

The use of a "global" controller may not be necessary, but it is always nice to have it around when a need arises. For example, I use it in my CMS to set a binding that initiates the loading of everything else - so all the sub controllers are loaded because of it. That isn't violating separation of concerns because the global controller's concern IS to facilitate the loading of other controllers.

That said, just be sure to keep things as modular/separated and reusable as possible. If your controllers rely on the global controller's existence in order to function, then there is an issue.

Upvotes: 10

krosullivan
krosullivan

Reputation: 172

In my opinion angular js' power comes with separating out clearly the different controllers directives, services, resources etc. Ideally controllers are linked to templates or partials and are used to update the front end and make calls to services or resources. The sooner you start making these separations the sooner you will start making clean and scalable apps that other developers can quickly make sense of. For app structure I would highly recommend you look into either of these two tools:

Lineman.js

and

Yeomann

The lineman site actually has a really good round up of how the two differ, if you scroll down.

In your scenario there are many ways to link controllers or make function calls that are in different scopes. You can either create a service that injects to your controllers or you can use $emit and $on to set up notifications in the app eg:

In controller A

$rootScope.$on('myNotifier:call', function() {
        myFunction();
    });

And in Controller B or any other controller you could call myFunction() with:

$scope.$emit('newPatientModal:close');

Upvotes: 0

Related Questions