Search code examples
angularjsangularjs-directivestandardsangularjs-controller

AngularJS: Why not write logic in controller?


Pardon me if this sounds stupid but I have been using AngularJS for a while now and everywhere I have seen people telling me to wrap my logic in a directive(or service ?) instead of my controller and keep only the bindings in my controller. Apart from the reusability aspect of a directive is there any other reason ?

Until now I haven't actually understood why this is the case. Doesn't writing a directive come with a lot of overhead ? I haven't faced any kind of problems writing logic in my controller and it is EASY. What ARE the downfalls of this approach ?


Solution

  • The controller is the right place to do all and everything that is related to the scope. It is the place where you write all the

    $scope.$watch(...)
    

    and define all the $scope functions that you need to access from your views ( like event handlers ). Generally, the event handler is a plan function which will in turn call a function a service.

    $scope.onLoginButtonClick = function(){
        AuthenticationService.login($scope.username,
            $scope.password);
    };
    

    On very rare occasions you can add a promise success handler in there.

    DONT: Write business logic in controllers

    There was a very specific reason why the earlier example was like that. It showed you a $scope function that was in turn calling a function in a service. The controller is not responsible for the login mechanism or how login happens. If you write this code in a service, you are decoupling the service from the controller which means anywhere else that you want to use the same service, all that you need to do is, inject and fire away the function.

    Rules for the Controller going forward:

    • Controllers should hold zero logic Controllers should bind references to Models only (and call methods returned from promises)
    • Controllers only bring logic together
    • Controller drives Model changes, and View changes. Keyword; drives, not creates/persists, it triggers them!
    • Delegate updating of logic inside Factories, don't resolve data inside a Controller, only update the Controller's value with updated Factory logic, this avoids repeated code across Controllers as well as Factory tests made easier
    • Keep things simple, I prefer XXXXCtrl and XXXXFactory, I know exactly what the two do, we don't need fancy names for things
    • Keep method/prop names consistent across shared methods, such as this.something = MyFactory.something; otherwise it becomes confusing
    • Factories hold the Model, change, get, update, and persist the Model changes
    • Think about the Factory as an Object that you need to persist, rather than persisting inside a Controller
    • Talk to other Factories inside your Factory, keep them out the Controller (things like success/error handling)
    • Try to avoid injecting $scope into Controllers, generally there are better ways to do what you need, such as avoiding $scope.$watch()