I am the beginner of angular js. I am struggling to understand the exact difference between the controller and directive in angular js.
In AngularJS, a Controller is defined by a JavaScript constructor function that is used to augment the AngularJS Scope. Controllers can be attached to the DOM in different ways.
AngularJS ng-controller Directive The ng-controller directive adds a controller to your application. In the controller you can write code, and make functions and variables, which will be parts of an object, available inside the current HTML element. In AngularJS this object is called a scope.
AngularJS directives are extended HTML attributes with the prefix ng- . The ng-app directive initializes an AngularJS application. The ng-init directive initializes application data. The ng-model directive binds the value of HTML controls (input, select, textarea) to application data.
No difference. It is same object.
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.
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 are mainly used for 2 things:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With