Reputation: 1474
I'm fairly new to angularjs. Im trying to understand why it's better to use this directive, compared to just using the controller. Both examples output the same value.
Directive Example:
angular.module('docsSimpleDirective', [])
.controller('Controller', ['$scope', function($scope) {
$scope.customer = {
name: 'Naomi',
address: '1600 Amphitheatre'
};
}])
.directive('myCustomer', function() {
return {
template: 'Name: {{customer.name}} Address: {{customer.address}}'
};
});
Markup:
<div ng-controller="Controller">
<div my-customer></div>
</div>
Controller Example:
angular.module('docsSimpleDirective', [])
.controller('Controller', ['$scope', function($scope) {
$scope.customer = {
name: 'Naomi',
address: '1600 Amphitheatre'
};
}])
Markup:
<div ng-controller="Controller">
Name: {{customer.name}} Address: {{customer.address}}
</div>
Maybe I just don't fully understand directives either.
Upvotes: 3
Views: 1011
Reputation: 16805
Controller:
A Controller is used to augment the Angular Scope.
When a Controller is attached to the DOM via the ng-controller
directive, Angular will instantiate a new Controller object, using the specified Controller's constructor function.
controllers use to:
Set up the initial state of the $scope object.
Add behavior to the $scope object.
Do not use controllers to:
Manipulate DOM — Controllers should contain only business logic.
Format input — Use angular form controls instead.
Filter output — Use angular filters instead.
Share code or state across controllers — Use angular services instead.
Directives:
At a high level, 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 or even transform the DOM element and its children.
Angular comes with a set of these directives built-in, like ngBind, ngModel, and ngClass.
you can create your own directives for Angular to use.
Generally directives are used to:
so if you need to reuse the same dom or logic in different place then you should use directive instead of controller.
Also you can access parent controller object from inner directive
Like:
<div data-ng-controller="mainController">
<p>hello world</p>
<some-directive></some-directive> // inject directive as element
</div>
Upvotes: 1
Reputation: 1726
There are multiple possible ways of how to bind functionality to template, some are better than others.
BAD - use ng-controller
attribute directly in html
template to
bind controller function to it
BETTER - use ngRoute
or ui-router
to specify routes/states or your application and there you can specify controller
and template
per route/ state
directive
definiton object where you can again specify both controller
and template
to bind them together and then use directive inside of templates and routes.The third example is than flexible in such a way that you can use directive just in any other template like <div my-directive></div>
but also in any router as a inline template like: template: '<div my-directive></div>'
The third approach is the best because it's going in direction of components which are the future (because of React, Angular 2.0 and Webcomponents). I wrote a blog post and created a sample github repository ilustrating these concepts.
Upvotes: 2
Reputation: 1382
At work, we use a simple exercise to see if we need a directive or not. If a certain snippet is used more than once, we turn it into a directive.
A directive also gives a chance to add less clutter to your templates.
angular.module('DocsSimpleDirective', [])
.controller('DocsController', [function() {
this.customer = {
name: 'Naomi',
address: '1600 Amphitheatre'
};
}])
.directive('myCustomer', function() {
return {
scope: true
restrict: 'EA',
controller: 'DocsController',
controllerAs: 'docsCtrls',
templateUrl: 'assets/template/my-customer.directive.html'
};
})
;
would allow your template to be defined as:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Angular test</title>
</head>
<body ng-app="DocsSimpleDirective">
<my-customer></my-customer>
</body>
</html>
and your directive as:
<article>
<strong>{{ docsCtrls.customer.name }}</strong><br>
{{ docsCtrls.customer.address }}
</article>
Personally, I try to refrain from using $scope
to bind data to. If somebody else starts to read your code, a magical customer
, defined in some controller somewhere on the scope is a lot harder to identify than a variable on a certain controller.
Isolating your $scope can be useful (by defining scope: true
) to use a a default value. If you need to stop isolating your directives, it should be something you thought about, not because it's the default value.
When you don't isolate a scope it inherits all values that are defined in the $parentScope
this is useful when nesting directives, where all directives should know which parent they originate from. This has a very distinct danger, you could manipulate data in the parentscope that shouldn't be manipulated.
https://docs.angularjs.org/api/ng/type/$rootScope.Scope
Upvotes: 5
Reputation: 15393
Other thing you need to set scope:true
.directive('myCustomer', function() {
return {
scope:true,
template: 'Name: {{customer.name}} Address: {{customer.address}}'
};
});
Upvotes: 2