What is the point of naming an anonymous function in a directive? - javascript

I came across some standards that basically said all the functions in directives and controllers in angular should be named. I am not talking about naming functions inside the controller or directive, I am talking about in the line where the directive is being called.
Example of how I would usually write this:
angular.module('myModule',[])
.directive('myDirectiveName', function (){
return{
controller: function($scope){
//some code
}
}
});
How this guide is asking it to be written:
angular.module('myModule',[])
.directive('myDirectiveName', function directiveInit(){
return{
controller: function controllerInit($scope){
//some code
}
}
});
Obviously, the difference here being directiveInit and controllerInit.
What is the point of this? Is it for better debugging errors? I know it is not needed. Does this make something easier? Is it an angular specific practice?
EDIT: Is there a better title I can use for this? I don't feel like the title is accurately reflecting what I am asking.

Well naming functions even if they don't seem necessary to be named, is a practice for maintainability resons.
One of them is to make the function trackable, for debug and profiling tools. When you are profiling your code to track performance issues, you better know the name of the function otherwise you will only see anonymous function which wouldn't help much on your profiling activity.
Other reason, is for code readability improvements, especially for teams. For exemple, in angularjs (v1.x) directives are very often declared like so:
(function(){
angular
.module('myModule')
.directive('myDirectiveName', myDirectiveName);
function myDirectiveName(){
function controllerInit($scope){
//some code
}
return{
controller: controllerInit
}
}
})();
Which in my opinion is way more easy to read than anonymous directive constructors. Also, it make more easy to handle such thing as encapsulation and stuff.

Related

Reusing functionality in angularjs controllers

I have a tree renderer that displays interactive nodes. Here is a piece of such interaction:
<div class="col-sm-10 pull-left box-content" ng-click="loadEdit(node)">
<div data-ng-if="!showEdit(node)" data-ng-include="formTemplates.display"></div>
<div data-ng-if="showEdit(node)" data-ng-include="formTemplates.edit"></div>
</div>
The functions showEdit(node) and loadEdit(node) are defined from the controller. I now need to have several pages with different logic - I want different controllers that each have their own showEdit(node) and a few other specialized functions but I would like to reuse the loadEdit(node) function and many others because they are definitely common functionality.
Here is the aforementioned loadEdit(node):
$scope.loadEdit = function(node) {
if ($scope.selectedNode != undefined) {
$scope.selectedNode.showEdit = false
}
node.showEdit = true;
$scope.selectedNode = node;
}
The common answer to reusing functionality is to make a service so I was going to make pass $scope to a service but a few people said that you shouldn't modify $scope in a service (I would love if somebody elaborated on why I shouldn't do that). Besides, all these functions are incredibly shallow and adding a layer of indirection and writing a bunch of definitions like these $scope.loadEdit = function(node) {return service.loadEdit(node, $scope.selectedNode);} wouldn't even solve the problem - if I wanted to also modify an another variable, I would have to add it to every controller that uses this service function (and the fact that javascript does not care about the amount of arguments passed makes such a task very easy to forget)
Perhaps there is some way of packaging those common functions into an object and adding them to each controller like this? Though, I wouldn't know how to distribute this object to the controllers:
angular.extend({}, FooCtrl, commonFunctionsObject);
angular.extend({}, BarCtrl, commonFunctionsObject);
angular.extend({}, BazCtrl, commonFunctionsObject);
...
Can you do this with a javascript library, perhaps? Any input is appreciated.

Why does angular define "priority" property for directives that are defined on the same DOM element?

I've found that angular doesn't take advantage of order the directives are defined in, instead it uses static priority field. It does not suite well for all cases.
Example:
<div ng-if="items.length < 50" ng-repeat="item in items"></div>
<div ng-repeat="item in items" ng-if="items.length > 50"></div>
These two lines of code can have different meaning.
Case 1) check if amount of items less than 50, ng-repeat 10000 items
Case 2) ng-repeat 10000 items, then on each element check if amount of items is less than 50
If ng-if had higher priority the first line of code would allow obviously very important optimization...
Obviously there is not much reason for using static "priority" field compared to prioritizing directives with order they are defined in, so my question is:
What steps should be taken to approve this idea and have it implemented?
(I was never looking into angularjs source code, some external help is required to point-out the places that need to be changed in order for providing the subject approach, I would be thankful for any external help in this direction)
Thank you in advance!
Edit
Here's a jsFiddle showing that ng-if is getting executed 20000 times for an array of 10000 items, each ng-if creates a scope which doubles the problem...
http://jsfiddle.net/u840t0dh/17/
I can't find a reason on why angular doesn't take advantage of order the directives are defined in, rather than using static priority field, it does not suite well for all cases.
The idea of angular directives is to extend browser built-in markup languages (tags, attributes, ...). I believe there is no such feature in standard browser markup. I want to stress that directives in angular is declarative programming.
For the problem you pointed out, it looks to me like imperative programming. It's like you're coding your logic in the page with an if and a loop. But in your case, it does not make much sense to use them on the same element => it's very similar to writing if and for loop on the same line in any imperative programming languages (c++, c#, java,...). It makes more sense to write it like this if you follow imperative programming mindset:
<div ng-if="items.length > 50">
<div ng-repeat="item in items"></div>
</div>
I agree that sometimes in order to write UI rendering code, we have to write a bit like imperative programming but it could be kept to the bare minimum. Even in those case, if you follow the mindset of imperative programming (like the one I pointed out), there should not be a problem.
Therefore, the problem you pointed could be a problem but actually not a big problem compared to the advantages that we gain from declarative markups.
Declarative programming and imperative programming has their own pros and cons:
http://en.wikipedia.org/wiki/Declarative_programming
https://softwareengineering.stackexchange.com/questions/32781/declarative-programming-vs-imperative-programming
For the case of directives to extend "markup", it makes more sense with declarative programming which is the way angular directives were designed (markup is really declarative)
The point of declarative programming is about telling "what" you want, not "how" to do it. That comes with the benefit: it's simpler and easier to understand.
From MSDN
In fact, the ease of understanding code—even in an unfamiliar
context—is one of the principal benefits of a declarative style.
The most notable benefit of declarative programming is that programs
specify “what” we want to get as the result rather than “how”. As a
result, it is more important to understand the domain that we’re
working with than every detail of the language.
With your suggestion, it's more about "how" you want to get a task done. The downside of your suggestion is that when we use directives, we need to understand how they work "internally".
For example: when you use many directives on the same element, the person who uses the directives need to understand what is the order to put the directives (that's should be the concern of the person who implements the directives). That's something declarative programming tries to avoid because it's complex for users of the directives
To answer your question, there are several possible use cases for Priority. I am not saying they are common, but they are possible and potentially very powerful…
Here are two examples:
Use case A) Wrapping any directive.
By using priority you can get custom code running before or after a given directive.
Suppose you have an existing angular application with thousands of ng-click directives, and want to run something before every single ng-click. You can do something like this:
angular.module('app', [])
.directive('ngClick', function($rootScope) {
return {
restrict: 'A',
priority: 100,
link: function(scope, element, attr) {
element.bind('click', function(ev) {
alert("custom click running");
})
}
}
})
.controller('MyCtrl', function($scope) {
$scope.alert = function() {
alert('built-in click running!')
}
})
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="angular.js#1.0.7" data-semver="1.0.7" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js"></script>
</head>
<body ng-controller="MyCtrl">
<a ng-click="alert()">Click me</a>
</body>
</html>
Here your custom click will run before angular build in click.
Use case B) terminating execution
By using priority and terminal: true, you can prevent other directives from executing. For example on all delete actions you can use a custom directive to ask for confirmation. in this case using DOM defined order will be dangerous because you are deleting records.
var app = angular.module('terminal', []);
app.controller('MainCtrl', function($scope) {
$scope.deleteIt = function() {
window.alert('Delete called!');
}
});
app.directive('confirmationNeeded', function() {
return {
priority: 10,
terminal: true,
link: function(scope, element, attr) {
var msg = attr.confirmationNeeded || "Are you sure?";
var clickAction = attr.ngClick;
element.bind('click', function() {
if (window.confirm(msg)) {
scope.$eval(clickAction)
}
});
}
};
});
<!doctype html>
<html ng-app="terminal">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.js"></script>
</head>
<body ng-controller="MainCtrl">
Delete with custom message
</body>
</html>

Should angular.module be set variable on AngularJS

I’ve read two AngularJS sample on Github. I’m confused to how to modularize controller. The first on is set variable(foodMeApp) and re-use it. Controllers need less arguments. It’s easier to read.
But, second one doesn’t use variable(foodMeApp) and has more arguments. I think this way is frequently used on AngularJS samples.
Is this any merit to use the second way?
1.https://github.com/IgorMinar/foodme
var foodMeApp = angular.module('foodMeApp', ['ngResource']);
foodMeApp.constant('CONFIG_A', {
baseUrl: '/databases/',
});
foodMeApp.controller('HogeController', function HogeController($scope, CONFIG_A) {
console.log(“less arguments");
});
2.https://github.com/angular-app/angular-app
angular.module('foodMeApp', ['ngResource']);
angular.module('foodMeApp').constant('CONFIG_B', {
baseUrl: '/databases/',
});
angular.module('foodMeApp').controller('HogeController', ['$scope', 'CONFIG_B', function($scope, CONFIG_B) {
console.log("more arguments");
}]);
since angular.module('...') ,constant,provide,controller,factory ... return the same mdoule you can chain module method calls if you want to or not... it's just javascript.
you can write
angular.module('foo',[])
.controller('bar',function(){})
.service('baz',functinon(){})
.constant('buzz',something)
.value('bizz',somethingelse);
it makes no different.
This example is using an array for your dependencies which are going to be injected into your controller. The array method is typically used when the code is going to minified at some time and allows angularjs to know exactly which items will be injected. If this array were not there, angular would only see 'a', 'b' as the items injected into the function and would not be able to figure out what those things were. Items in the array are strings and will not be changed when the minification happens.
angular.module('foodMeApp').controller('HogeController', ['$scope', 'CONFIG_B',
function($scope, CONFIG_B) {
console.log("more arguments");
}]);
Hope this helps explain the differences which you have seen.
There is no such 'merit' of going for 2nd option. 1st approach is more popular as it avoids repeating angular.module('foodMeApp') so many times.
If you give it a name "foodMeApp" you can directly use foodMeApp as you would have used in 2nd approach. Less repetition, simpler life.

AngularJS Controllers: The Right Way

So, I've been talking with co-workers about the "right way" to create an AngularJS controller. I know there are several ways of creating one, but I'm interested in getting my team writing them the same way AND the "right" way. By "right way" I'm talking about easy to read, testable, and performant. I'm sure there are competing theories on the best way to create a controller, but I'm most interested in test-ability at the end of the day since that is what AngularJS is built to do well.
Without further ado, here's the contenders:
Let's assume that our app is declared as so: var app = angular.module('app',[]);
1.
app.controller('myCtrl', function(){
...
});
2.
function myCtrl = {
...
}
app.controller('Ctrl', myCtrl);
3.
(function(app) {
app.controller('myCtrl', function() {
...
}
})(app);
Please let me know if I've missed one.
This does not take into consideration the changes needed for minification so please do not add that to this conversation.
Thanks! (I hope this doesn't start a flame war ><)
My team exclusively uses 1. I've considered 3 as well, and we just have a standing rule (and jshint constraint) about global level code. I would never use 2.
I always do it this way:
angular.module('myModule').controller('MyController', ['$scope', function($scope) {
<stuff>
}]);
Yes, it's a little more verbose, but it creates nothing in global scope, it is very clear what module the controller belongs to, and if I need to separate my controller into another file I just copy and past it without worrying about where 'app' is defined or about whether I missed a '.' in a chained declaration.
And I know I was supposed to ignore it, but of course this version is minification safe.
In general I believe you should find a clear standard and stick to it. That way if something doesn't look "right" you can tell right away.
The Angular team recently posted a best practices guide so that might be a good place to start: http://blog.angularjs.org/2014/02/an-angularjs-style-guide-and-best.html. Also this presentation discusses some best practices on creating controllers: https://docs.google.com/presentation/d/1OgABsN24ZWN6Ugng-O8SjF7t0e3liQ9UN7hKdrCr0K8/present?pli=1&ueb=true&slide=id.p
If you were using number 2 you wouldn't really need app.controller('Ctrl', myCtrl);. You can reference a controller from ng-controller even if it isn't defined with module.controller(...)
You might want to also consider making your controller as much like "classes" as javascript will allow and using the 'controller as' syntax.
var myApp = angular.module("myApp", []);
myApp.MyCtrl = function($log) {
this.$log = $log;
}
myApp.MyCtrl.prototype.sayHello = function() {
this.$log('hello');
}
There are cases where it may be useful to have your controllers globally accessible. Like if you want to create an instance of your controller with $injector.instantiate() you need to have access to its constructor (although you could use the $controller service to accomplish the same goal using a string).
var myCtrl = $injector.instantiate(myApp.MyCtrl); //Works
var myCtrl2 = $injector.instantiate('MyCtrl'); //Doesn't Work
But if you don't have a specific use case for making your controllers global you should probably encapsulate them with module.controller(...);.
This answer also advocates using module.controller() https://stackoverflow.com/a/13363482/373655

Interface Segregation Principle in jQuery

Anyone able to give a good illustration of how this works in jQuery?
Specifically with regards to the answer from here.
It sounds the same as Single Responsibility Principle (SRP) for OOP? How is it different?
I feel more comfortable with answering my own question now.
With Single Responsibility Principle, I'm thinking mainly of objects created like in a game. That object should be responsible only for itself, in terms of internal functions/methods.
As for Interface Segregation, I'm thinking more of avoiding anonymous function calls, and segregating a large chunk of code... to different named calls. This was well explained by Paul Irish in jQuery Anti-Patterns for performance.
Instead of anonymous functions bound everywhere like
$(function() {
//do stuff related to setup menu
//add facebook, twitter widgets
//more anonymous actions....
}):
Segregation into a well defined interface might look something like the below:
var homepage = (function() {
function setupMenu() {
//do stuff related to setup menu
}
function setupSocial() {
//add facebook, twitter widgets
}
return {
setupMenu:setupMenu,
setupSocial:setupSocial
}
})();
$(function() {
homepage.setupMenu();
homepage.setupSocial();
})

Categories

Resources