Placing directive logic inside controller rather than link - angularjs

I have a general question. I've recently seen plenty of examples of people putting all their directive logic in a directive controller (and using it with controllerAs) instead of using link. I do see certain benefits in that:
The directive logic can be easily unit-tested.
You are seamlessly obligated to use the "dot notation" in your view model, thus prevent unexpected behavior.
As for the disadvantages - once the logic is inside the controller, it is exposed to other directives, as if encouraging developers of other directives to access those variables/methods, even if they are not meant to be accessed from outside.
I am interested in getting your take on this? How do you organize your code inside the directive.
Thanks

I am using Angular for about 4 months so I cannot
Say that I have too much experience. However in my
Personal experience I used the controller only for logic
That needs to be shared or executed before the link
Function. I guess you can hide some logic from your controller by using the module pattern and only exposing the logic that is really necessary. In my defense I haven't wrote really complicated controllers but this is the way I would go. (Sorry for my bad writing I am responding from my phone)

Related

$compile vs $componentController

I'm relatively new to Angular and have begun writing my application with a component architecture. When looking through the Angular docs it recommends testing components with the $componentController mock method.
However, when I look at how directives have traditionally been tested in Angular pre-1.5 it looks like the preferred method was to use the $compile service to actually build your directive template-and-all. By using $compile you can make assertions about your template logic as well as the controller logic. Whereas with the $componentController method you can only test the controller logic, which doesn't actually seem all that useful since most complexity is found in templates and services.
Can someone shed some light on modern best practices? To me it makes more sense to use $compile so that you can test the template as well. But why do the Angular docs not mention this at all and instead recommend $componentController?
One of the biggest problems with AngularJS is that it has $scope. This is the place you put your bindings onto that are used in the DOM. It introduced much confusion.
Every good application design should have layers: business logic, UI etc. In AngularJS those layers pretty much corresponded to controller for business logic and directives for UI. However, because of the $scope being available in directives, many people decided to not use controllers and put all business logic in directives. This led to hard-to-test directives because they simultaneously implemented both layers. Also test became slow since DOM manipulation is slow.
Ideally, you should put as much testing as possible into business logic and less in the UI. Since framework handles synchronization between business logic and UI there is little possibility of bugs there. But business logic is where most bugs are introduced. That's why in the newer AngularJS they recommend to use $componentController to test business logic in controllers, not directives.
New Angular doesn't have $compile and most tests are written for controllers, which are implemented as classes there.

Using directives in real life angular app, are directives with controllers a right approach?

I know that this topic was discussed many times but I'm still not quite sure if I'm doing things right..
Many on-line resources embrace directives as a building blocks of the angular applications, in the same time many resources emphasize re-usability of the components. Anyway from my experience when I build typical app, there is not much things to re-use, usually each component has single role and it is used in the single place. As I understand angular, one of the main concepts is to provide semantic DOM, and in order to achieve that we can use directives. So when I build an angular app usually I create a set of directives and combine them in the views.
In my apps in the most cases all the DOM manipulation can be done using the build in directives. Most of my directives has a template and a controller, I do not need to use link function. In most of the resources in the internet I can read that I should use link function when creating directives. But this seems to be far more complicated code... . What is the benefit of the link function if I don't need any fancy DOM manipulations that are beyond build-in directives ?
tldr; I build my apps using directives with controllers and put them into views, is this a right approach ?
I've been developing in Angular over a year now on an enterprise level application and my team has gone by a standard of creating directives if you are using that same element more than once. It saves time, saves the DOM trouble, and makes it easy to create separate, testable pieces of code.
We've created directives for many listing items that use ng-repeat. Pretty much every ng-repeat we have is iterating over a directive to create true isolate scope in our elements' functionality. It's one of the most powerful features in AngularJS when done right and conforms to the standards of Object Oriented Programming where you can really make your applications use abstraction to the finest degree. Here's a wiki link on abstraction.

Seeing examples of directives used as controllers

I am reading this article: http://icelab.com.au/articles/an-all-in-one-directive-controller-with-angularjs/
I think it would be a better practice to use a controller with ng-template in this example, as I see nothing here that is altering the DOM.
Why is the author using directive?
If you think this is a bad practice, could you elaborate more as to why?
The idea is that it's completely modular and can be easily included in other Angular apps. The whole point is that it's acting as a "widget."
While it's great to keep DOM manipulation contained in directives (this is for easy testing), it doesn't mean you can't make non-DOM related directives. In fact, it's common to have large directives that have absolutely no bearing on the UI whatsoever. For example, a directive that handles local-storage or cookies.
It is worth mentioning directives have to be stamped out from the DOM in the first place (via attribute, element, class, etc.). This the idea of the declarative model.

AngularJS: Is ng-click "a good practice"? Why is there no ng-{event} in AngularJS?

I just started to learn AngularJS and struggle with some concepts of AngularJS. It would be great if somebody could explain me some points...
I understand that ng-click is technically not the same as onclick (see here), but both are placed in the markup. I thought that would be a "bad practice"? Why is this one of the core concepts of AngularJS, if most people say this is "bad"? I thought it would be better to select the DOM element from JavaScript and not to place logic in the markup.
If ng-click is the right way to react to click events in AngularJS what should I do with other DOM events? I see that there are several other directives like ng-mouseover, but not all DOM events have a AngularJS equivalent. How would I handle a 'drop' event in AngularJS (hence in the AngularJS way - not the normal way)? To be clear: I want to drag a file into my webapp.
Thank you very much,
Pipo
Why is this one of the core concepts of AngularJS, if most people say this is "bad"?
Well, people who really like Unobtrusive JavaScript might say it is bad. Angularians (and those with a flex background) see value in the more declarative approach.
"Angular is built around the belief that declarative code is better than imperative when it comes to building UIs and wiring software components together... By declaratively describing how the UI should change as your application state changes, you are freed from low level DOM manipulation tasks. -- Overview doc
See also Don't the data attribute options used in Bootstrap, Angular.js, and Ember.js conflict with Unobtrusive Javascript principles?
what should I do with other DOM events?
Write your own directives to listen for them (or find one that someone else has already written). Angular gives you the power to extend what the browser can do -- by writing your own directives.
Update: in the comments below, Tim Stewart mentions AngularUI's ui-event, which lets you bind a callback to any event not natively supported by Angular.
By nature, Angular requires elements in the markup in order to function properly. Further, those elements must be "compiled" each time they change, for the most part. So, it's already somewhat "obtrusive" irrespective of the JavaScript. You can't simply replace the markup, and have everything auto-bound for you like you can with something like jQuery.
Strictly speaking, unobtrusive JavaScript:
1. separates structure and behavior, in order to make your code cleaner and script maintenance easier
2. preempts browser incompatibilities
3. works with a clean, semantic HTML layer
(Wikipedia)
That's not Angular, for sure. In order to achieve the two-way binding on everything, they chose to make custom binding points in the DOM, as opposed to using a class name or ID the way that jQuery would do. (A somewhat non-standard approach, but it obviously works.)
But the real way to think of it is this: Basically each controlled section of your markup is not really straight HTML anymore anyway. It's really more of a template now, and as such requires interaction with the engine that is preparing it for rendering. As such, the traditional rules of unobtrusiveness don't really apply... (FWIW, I'm a huge fan/user of the jQuery.on() function to bind elements to events automatically when the element is added to the page. Very clean and flexible, IMHO, and I do wish there was a similar mechanism in Angular. I like adding a class to items in multiple locations on the page that invoke the same event handler automatically. Having a single place to go change code is a good thing. but I digress...)
For me, the bigger issue is that of progressive design. Does the web page work without JavaScript enabled at all? Does anyone really care about that? Hmmm...

App architecture: directives vs. controllers

I have a big app, which contains many layouts and subviews.
Looks like (simplified):
http://plnkr.co/edit/x4kleCCQH5Hsy6dcjgXe?p=preview
So, I have many directives and services. And only 2-4 simple controllers (10 - 20 lines of code). All logic stored into big directives, which contain many small directives. Am I wrong?
The way I'm approaching it is.
Directives contain view logic, not business logic. This is also where DOM-messing about happens if needed.
Controllers are fairly thin, have minimal business logic.
Angular Services are where most of the heavy lifting is done.
If you have logic that needs to be re-used by multiple areas/controllers or is stateful - it's probably a better fit to put into a Service than a Directive.
Depending on your app/architecture - you could be posting to a server, and having the heavy BL happen on the server side.
The Angular docs have a nice bit on Using Directives Correctly that has a few pointers.
Sounds good to me.
At some point in the DoubleClick talk, the speaker says something similar to "make controllers as thin as possible."
The link was busted... a working link to the same guide is here:
http://docs.angularjs.org/guide/controller

Resources