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.
Related
Sometimes forms has some logic: some additional data requested with ajax, it reads cookie or has a special filter. I would like to separate this logic from controller. I also would like to have forms' html in a separate file. How to achieve this?
Is it possible to make factory or service work with form?
I have an idea about implementing each form as directive. Would it be good solution?
EDIT:
The main goal is not to move HTML to separate file but to move the form logic out of main route controller. Is it possible to write some provider that takes care of the form so that all data queries for the form select elements (and other logic) is happening in this provider and it calls controller's function just at the end to save validated data?
I also would like to have forms' html in a separate file. How to achive this?
You can use ready made directives like ng-include to include external HTML fragments, or you can have your own template-expanding directive.
Is it possible to make factory or service work with form?
You can create any provider whose operation is dedicated to handle form(s). This is your model than an angular technique.
I have an idea about implementing each form as directive. Would it be good solution?
If you have many forms in your application and they are playing a pivotal role, yes - having directives for forms could be termed as a specific solution. The pros and cons cannot be explicitly judged here since the rest of the application's character is unknown.
Probably this is one of the places you should start your research from.
Your question is too broad. If you would like to separate the form from the controller, you need to put that form into a directive, which would allow you to put the html and javascript for the form in a separate file.
Another way to put the form html in a separate file is to use ng-include, however, this simply lets you move the html, whereas the first method will allow you to have a separate controller for the form html.
I have an idea about implementing each form as directive. Would it be good solution?
I believe that is THE solution you are looking for.
I would like to know when does it make sense to use multiple controllers on the same page in angularjs. Also, when should one think about separating a controller into multiple controllers?
You should largely have your functionality in providers (services or factories typically) and your controllers should have very little in them aside from getting the providers injected (and exposing models and functions for use in the view) and possibly some view specific functionality (configuration for directives used only in one place etc.). You can have multiple controllers on the page if you decide to build the views within a page to be portable.
If you have one controller that shares the functionality needed for disparate parts of a page and later decide to move one part of the view to another route/state/view then you'll need to piece apart the controller. I don't think there are any hard rules really but if your controller is more than 100 lines you're probably making it responsible for too much and should "promote" some things to be handled by providers and/or start splitting things up a bit more.
The answer would be dependent on your page requirement. Having multiple controllers can easily be done.. But issues pop-up when you wanted to have page flows.
Controllers are just a part of AngularJS.. Usage of services, factories and filters is a recommended way of splitting your code along with controllers. If multiple controllers per page becomes imperative.. try utilizing directives. Also consider using Views provider by UI router.
I use multiple controllers when my page has got multiple pop-ups with complex functionality and i want separate controllers for them so that logic behind each-pop is in its own controller.
Similarly, I create separate controllers for sidebars and header and footers on the same page.
These are few examples which comes in my mind when using multiple controllers on same page makes sense.
But as others have mentioned, you should use providers and services/factory for splitting your code.
There are two ways (AFAIK) to associate a controller with a view template/partial: the route specified in $routeProvider and the ngController directive. Especially (but not exclusively) for simple routing, is there any benefit/efficiency of one over the other?
My project currently uses the $routeProvider approach, but I've been given the task of nesting views. This seems simple enough with ngInclude, as long as the partial specifies its ngController.
This question really comes down to design and as such it is a bit opinion based. That in mind, the best guidance I know is:
$routeProvider - Allows you to specify a single controller for a template. Since this is part of the routing it makes it easy to find the controller that goes with the page. I use this to store and load overall page logic rather than element specific logic.
This is also important because it means you can load the exact same template for two different routes but the behavior and data could be different because the controller can be changed. This is not something that is easy to do with the ngController option.
ngController - This scopes the controller to a specific element on the page/template. That can make the code easier to read when you need multiple controllers on a single page and it allows the controller to be more specifically scoped.
So it really comes down to scope and intent. Hopefully these rules will help when deciding which to use.
If you think of a view including all scripts as a self-contained package, developed by a single person or team, then ngController is the way to go, imho.
$routeProvider on the other hand provides you with advanced features like injection of values via the resolve property of the route. That way you can have your AJAX loaded data directly injected into your controller, e.g., instead of the controller having it to get itself. Or have the route change to wait for that data etc.
Btw: If you need routing and nested views you can take a look at angular ui-router
I'm new to AngularJS and having a hard time wrapping my head around the conceptual model.
Let's say I want to have an object hierarchy to model a stash repository: Projects contain Repositories contain Tags. Do I create one app, one module and multiple controllers? (Can a module have multiple controllers?) Separate app per object type? Separate module per object type?
All the various data types will be populated by making REST API queries. Read-only for now. Does that change things?
Also, why are they called controllers? They seem to be models. As far as I can tell the controller is actually the AngularJS plumbing.
Here is my rather simple explanation:
A module is just simply a container for all the bits and pieces of your app (services, controllers, directives, filters etc).
Your application may contain different modules - some that you wrote and other third party ones, such as ngGrid for example.
You define a module like this:
var myAppModule = angular.module('myApp', []);
A controller is where the business logic of your application resides. The controller may handle the model, but it is not the model.
The AngularJS documentation for controllers states:
Use controllers to:
Set up the initial state of the $scope object. Add behavior to the
$scope object.
I break up my controllers in to the logical functions that they are supposed to handle. For example, I've written an app to help with combat tracking in a tabletop RPG. I have a controller that handles martial combat and another that handles magick. I also have another controller that helps with the characters. All these controllers are part of my combat app.
I only have one service that is responsible for querying a REST API to retrieve stats and results from a database.
The AngularJS documentation has improved a lot recently and I would recommend reading through it to give you a rough idea of how things work together!
In your example, I'd have a separate controller for each of Projects, Repositories and Tags. I'd have a service to query your datatypes. These would be grouped as part of one module/app.
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.