kalles
kalles

Reputation: 337

What is the difference between controller and directives in angular js?

I am the beginner of angular js. I am struggling to understand the exact difference between the controller and directive in angular js.

Upvotes: 9

Views: 10001

Answers (3)

Ahmed Wagdi
Ahmed Wagdi

Reputation: 934

There's a bit too much going on here to be able to fully explain each so i'll try to give a brief explanation of each as well as an example.

Controllers

Use controllers to handle the logic of your views and assign the data you want to appear in your view. For example if in your application you have a page called "All Users" you want to display a list of users you would, define an array of users and attach it to the $scope object in your controller.

var myApp = angular.module('myApp',[]);

myApp.controller('allUsersController', ['$scope', function($scope) {
  $scope.users = [
    { name: "User 1", id: 1},
    { name: "User 2", id: 2},
    { name: "User 3", id: 3}
  ];
}]);

Attaching the users array to the scope allows you to access this data from the view. So now in the view you can use ng-repeat to output the list of users:

<ul>
 <li ng-repeat="user in users">{{user.name}}</li>
<ul>

Directives

Directives are mainly used for 2 things:

  1. Creating reusable components
  2. Manipulating the DOM

Directives are tricky to use at first but are extremely powerful, this statement from the docs is the reason why they are so powerful:

Directives are markers on a DOM element (such as an attribute, element name, comment or CSS class) that tell AngularJS's HTML compiler ($compile) to attach a specified behavior to that DOM element (e.g. via event listeners), or even to transform the DOM element and its children.

The main point to take away from that is that directives allow you to attach certain logic/behavior to a certain element, where as controllers usually only allow you to attach logic to pages/views.

Lets say that in the previous example we wanted to add some actions that can be done in the user list, maybe a like and dislike button. We could just create like and dislike buttons like this:

JS

var myApp = angular.module('myApp',[]);

myApp.controller('allUsersController', ['$scope', function($scope) {
  $scope.users = [
    { name: "User 1", id: 1, like: 0},
    { name: "User 2", id: 2, like: 0},
    { name: "User 3", id: 3, like: 0}
  ];

  $scope.like = function(user){
    user.like++;
  }

  $scope.dislike = function(user){
    user.like--;
  }
}]);

HTML

<ul>
 <li ng-repeat="user in users"> 
   {{user.name}}
   <button ng-click="like(user)">LIKE</button>
   <button ng-click="dislike(user)">DISLIKE</button> 
 </li>
<ul>

Fairly simple, we add like/dislike methods in our controller that increment/decrement the amount of likes a user has. This code will work fine, but what if i wanted to create another list of users in a different view? Say that you have 3 different views which contain user lists: "All Users", "My Friends" and "Recommended Users", all 3 will have a list of users that have the same actions (like or dislike) but the users displayed are different in each. We want to use the same like/dislike methods that we defined in our allUsersController but we are on a different view so we can't access them, so you would have to copy the same code into the controllers of the other views, might not seem like a big deal in our example but as applications get larger and more complicated this gets very tedious and hard to maintain.

This is where directives come in, instead of assigning the logic behind each user item in the controller you can define it in a directive:

app.directive('userItem', function() {
return {
    template: '<div>{{userData.name}} <button ng-click="like()">Like</button> <button ng-click="dislike()">Dislike</button>',
    scope: {
      userData: "="
    },
    link: function(scope, element, attrs) {
      scope.like = function(){
       scope.userData.like++;
      }

      scope.dislike = function(){
       scope.userData.like--;
      }
    }
}
});

In your html:

<div class="user_list>
   <user-item ng-repeat="user in users" user-data="user"></user-item>
</div>

By using the user-item directive you can now create a list of users anywhere in your application without having to redefine the logic that goes with each user. You'll notice that this also cleans up our html a bit and saves you on repeating code a lot. The directive wraps up your html and js into a reusable component.

EDIT: Regarding how we're passing the user data to the directive, this has to do with the isolate scope in directives which you can read about here. The basic idea is that it isolates the scope of the directive from the parent scope (allUsersController in our case), this is done to avoid unwanted clashes between the data in the 2 scopes and to promote re-usablity. But at the same time there is some data that we want the controller to share with the directive, so we "poke a hole" through the isolate scope to allow certain things in, which in our case is the userData defined in the directive scope.

You can visit the directives docs and scroll down to isolate scopes for more examples.

Upvotes: 15

Saurabh Verma
Saurabh Verma

Reputation: 192

A controller is usually used to contain and maintain the logic for your view, which gets bound to your view via $scope.

A directive is something that you might use repeatedly and is called in your view directly through the directive name which you can pass in as an attribute.

Examples: ng-if , ng-repeat, are all directives.

you can make your own custom directives for some code or logic which is used repeatedly in your code.

A good read to use and impliment directives is: http://kirkbushell.me/when-to-use-directives-controllers-or-services-in-angular/

Cheers!

Upvotes: -1

anotherdev
anotherdev

Reputation: 2569

A controller is a js function that will be executed if you use ng-controller='MyController' in the html.

It can be called with angular-route automatically depending on your url.

A directive is a custom HTML element on which code can be applied. A directive can container either a html template, either a link function to execute, either both.

Example of directive: ng-repeat, ng-model, ng-include.

Upvotes: 0

Related Questions