Nested controller vs directive in AngularJs - angularjs

Could any angularjs guru please tell me when is it better to use nested controller and when to use directive.
Up until now, I've used mostly directive and cannot think of a scenario where I would chose to write a child controller.

My take:
Use:
Controllers (nested) for hierarchical relationships, parts of a page with different purposes are typically child controllers of the page controller.
Directives for stand-alone components that can be reused anywhere/in multiple places. Especially when DOM manipulation is involved, a directive is the right choice. Example: a custom drop down control.
Services for sharing data between controllers that are not nested (no parent/child inheritance).

Related

AngularJs controller and directive purpose, the right way?

I've been reading up a more in depth about angularjs directive and controller, what should be in one and the other. The situation is this, I have multiple people with their types -> policemen, medicine, lawyers ... etc. inside the admin panel app, where the admin can manage them. In one section the admin can create, edit, delete them. The current versions controller does almost all the work: UI (bringing up the right form, hiding the other forms...), and logic (deleting, creating, updating methods for each person type). As I understand this is not good, because the controller does multiple things (no single responsibility). And even further the controller should only bind values to scope.
But does that mean, that I should only pull all the people (inside controller) and pass it some master directive which will manage it all? Or should their be more directives inside directives to divide the responsibility?
And if so, the controller will have to use the same service as the directive/directives. Controller for pulling people from back-end) and the directive/directives (for creating/updating/deleting) is this DRY?
Without code it's hard to give a precise answer, but the general idea when working with angular is this:
Controller: The controller is responsible for keeping the views up to date with all the changes that are happening throughout your app. This means that it should not contain the business logic, this logic should instead be separated into small services. Each handling different parts of the logic for your app.
Service: As stated above, a service should contain your business logic. Meaning that heavy calculations, manipulations etc. should be put into a service. Since services are singletons you can easily inject this service anywhere and re-use the logic within it, something you cannot do if you've put your logic inside a controller.
Directives: Like controllers, directives shouldn't have any business logic in them. Directives are only there to create re-useable functionality as well as giving you a place to handle direct DOM changes. DOM changes should never be done anywhere but from within a directive.
To answer this:
And if so, the controller will have to use the same service as the directive/directives. Controller for pulling people from back-end) and the directive/directives (for creating/updating/deleting) is this DRY?
If you have the data bound to a controller, you should not necessarily need a directive to handle the CRUD operations. Since the data is bound to the controller, you can easily create a template which reacts to the data changes automatically using ng-repeat, ng-if and so on.

Dom manipulation in AngularJs

I wanted to know, If we want to manipulate the DOM. Where we should do that.
Is it in a Controller or a directive or somewhere else ?
I have read somewhere that manipulating the DOM in controller should be avoided. Is it correct?
You should use Angular JS Directive for DOM manipulations. DOM Manipulations should not exist in Controllers, Services or anywhere else but in Directives.
One of the nicer features of AngularJS is the framework's ability to separate the roles of the model, the view, and the controller. The separation is clean enough that you shouldn't need to manipulate the DOM directly from code inside the controller. Instead, the controller only manipulates the model, which influences the view through data bindings and directives. The end result is a clean and testable.
Take a look at this
Video - This video tutorial covers manipulating the DOM in AngularJS using directives with a link function.
Best practice is:
Dom manipulations only in directives.
Read here

Trying to understand the concept of AngularJS

I have started playing around with AngularJS and I am having a hard time understanding directives and scope.
If I understand correctly, you create directives to create reusable components that contain behavior and logic to modify the DOM?
So do directives get services injected into them?
Or do you use a controller with the directive that has services injected into it?
I guess I am really struggling on the relationship between the directives with controllers and services as well as scope.
Are there any good tutorials out there that explain this in an easy to grasp way?
You can inject a service into a directive or a controller. One thing that helped me was hearing that the only place DOM manipulation should happen is in a directive.
Controllers should be the glue between views and services and basically handle view behavior. They should be thin
Services manage logic independent of the view (and are singletons).
So think more declarative, less iterative. Overall, represent state in models. Then set up bindings so you can change the model and the view automatically changes (From: http://www.youtube.com/watch?v=oJoAnVRIVQo)
You might check out the Angular team's youtube channel: http://www.youtube.com/user/angularjs
And here's some good tutorials: http://egghead.io
Services are meant to persist state across your entire app.
- Most of the time they will exist within your controllers
- they can be injected into your directives
Controllers are meant to perform business/app logic with the values passed in from the view.
Directives are useful for:
- creating reusable components
- adding behavior to the DOM or Forms
http://docs.angularjs.org/api/ng.directive:ngModel.NgModelController
Scope is the context within the app that a directive or controller has access to.
- with controllers, the scope is limited to the DOM
element to which it is assigned and its children elements.
- with directives, the scope can be the same scope as the scope of the controller
or be its own scope (isolated from all other scopes), or its own scope
prototypically inherit from its parent scope.
i recommend the videos at http://egghead.io
Trying to understand the concept of AngularJS
Please read THIS response written by Josh David Miller.
I think it will be good start for who knows jQuery but still beginner in AngularJS.
If I understand correctly, you create directives to create reusable components that contain behavior and logic to modify the DOM?
Directives are most difficult piece in AngularJS (at least for me). For sure you can do Service injection on Directives, like:
app.directive('changeMe', ['$compile', 'myService', function($compile, myService){
return {
restrict: 'CA',
link: function (scope, element, attrs) {
scope.value = myService.value;
}
}
}]);
services
The key benefit of services is that it provides the formal mechanism for code reuse. Any shared piece of business logic can be moved to service to improve maintainability of your code by avoiding code duplication. Services like utilities, you can grab them (all services should written in separate JS file) and import to other Projects easily.

Creating a service that updates the DOM

I am trying to create a web application and I need little widgets that should be available from all controllers (i.e. a loading overlay and a sliding drawer). I have created directives with methods to display such behaviour, but you can't inject directives in controllers, that's not how they work.
I know I have to create a service that deals with this, and inject it in both controller and directive, but still can't figure out how to make the communication. The elements that have the directive are unique.
Another option I've considered is to create event listeners in the $rootScope or somewhere else and call $emit from all controllers that might need it, but I feel like the other way is more angular-y
Your "widgets" need ng-controller directives. I think this is what you're looking for:
<div ng-mywidgetdirective ng-controller="mywidgetcontroller"></div>

What is the difference between service, directive and module?

I have been reading a lot of docs, and I'm getting more and more confused.
I basically can't figure out the difference between a
service
directive
module
I see a lot of custom components. Sometimes they're using directives, sometimes services. It always starts with a module. Can someone explain with an example what the difference is between these three types?
From my own personal notes (mostly snippets from the docs, google group posts, and SO posts):
Modules
provide a way to namespace/group services, directives, filters, configuration information and initialization code
help avoid global variables
are used to configure the $injector, allowing the things defined by the module (or the whole module itself) to be injected elsewhere (Dependency Injection stuff)
Angular modules are not related to CommonJS or Require.js. As opposed to AMD or Require.js modules, Angular modules don't try to solve the problem of script load ordering or lazy script fetching. These goals are orthogonal and both module systems can live side by side and fulfill their goals (so the docs claim).
Services
are singletons, so there is only one instance of each service you define. As singletons, they are not affected by scopes, and hence can be accessed by (shared with) multiple views/controllers/directives/other services
You can (and probably should) create custom services when
two or more things need access to the same data (don't use root scope) or you just want to neatly encapsulate your data
you want to encapsulate interactions with, say, a web server (extend $resource or $http in your service)
Built-in services start with '$'.
To use a service, dependency injection is required on the dependent (e.g., on the controller, or another service, or a directive).
Directives (some of the items below say essentially the same thing, but I've found that sometimes a slightly different wording helps a lot)
are responsible for updating the DOM when the state of the model changes
extend HTML vocabulary = teach HTML new tricks. Angular comes with a built in set of directives (e.g., ng-* stuff) which are useful for building web applications but you can add your own such that HTML can be turned into a declarative Domain Specific Language (DSL). E.g., the <tabs> and <pane> elements on the Angular home page demo "Creating Components".
Non-obvious built-in directives (because they don't start with "ng"): a, form, input, script, select, textarea. Under Angular, these all do more than normal!
Directives allow you to "componentize HTML". Directives are often better than ng-include. E.g., when you start writing lots of HTML with mainly data-binding, refactor that HTML into (reusable) directives.
The Angular compiler allows you to attach behavior to any HTML element or attribute and even create new HTML elements or attributes with custom behavior. Angular calls these behavior extensions directives.
When you boil it all down, a directive is just a function which executes when the Angular compiler encounters it in the DOM.
A directive is a behavior or DOM transformation which is triggered by a presence of an attribute, an element name, a class name, or a name in a comment. Directive is a behavior which should be triggered when specific HTML constructs are encountered in the (HTML) compilation process. The directives can be placed in element names, attributes, class names, as well as comments.
Most directives are restricted to attribute only. E.g., DoubleClick only uses custom attribute directives.
see also What is an angularjs directive?
Define and group Angular things (dependency injection stuff) in modules.
Share data and wrap web server interaction in services.
Extend HTML and do DOM manipulation in directives.
And make Controllers as "thin" as possible.
Think of a module as being a place to wire up a number of other things, such as directives, services, constants etc. Modules can be injected into other modules giving you a high level of reuse.
When writing an angular app, you would have a top-level module which is your application code (without templates).
Services are mainly a way to communicate between controllers, but you can inject one service into another. Services are often used as a way to get to your data stores and people will wrap the angular APIs, such as ngResource. This technique is useful since it makes testing (particularly mocking) quite easy. You can have services for doing other things like authentication, logging etc.
Directives are used for creating widgets or wrapping existing things like jquery plugins. Wrapping existing plugins can be a challenge and the reason you would do this is to establish a two-way data binding between the plugins and angular. If you don't need two-way data binding then you don't need to wrap them.
A directive is also a place for doing DOM manipulation, catching DOM-events etc. You should not be doing DOM-related stuff in controllers or services. Creating directives can get pretty complex. IMHO, I recommend first looking at API for something that can do what you are looking for OR ask Angular's Google Group for advice.

Resources