Top 10 Mistakes AngularJS
Developers MakeMark Meyer
@nuclearghost
About MeSoftware Engineer at
Sharethrough
Developing on AngularJS since
1.1.5 (triangle-squarification)
Built ~40k line AngularJS app
and many much smaller
AngularJS apps
What’s the
point?AngularJS === Awesome
Easy to Start
Learning Curve Eventually
Ramps up
My Experiences from
building a large application
The Mistakes
1. MVC Directory Structure
2. Modules
3.
4.
5.
6. Batarang
7. Too Many Watchers
8. Scoping $scope’s
9. Manual Testing
10. Using jQueryServices v Factory
Dependency Injection
Controllers Bloat
Dependency Injection
Great Design Pattern for Testing and Parallelizing Development
Not the prettiest in AngularJS
var app = angular.module('app',[]);
app.controller('MainCtrl', function($scope, $timeout){
$timeout(function(){
console.log($scope);
}, 1000);
});
Array Style
+ Safe for minification
- Extra in-line code
app.controller('MainCtrl', ['$scope', '$timeout', function($scope, $timeout){
$timeout(function(){
console.log($scope);
}, 1000);
}]);
$inject
Property attached to controller functions
Not as convenient for in-lining
Potentially cleaner without duplicate names at declaration
var MainCtrl = function($scope, $timeout){
$timeout(function(){
console.log($scope);
}, 1000);
};
MainCtrl.$inject = ['$scope', ‘$timeout']; //or MainCtrl[‘$inject’]
app.controller('MainCtrl', MainCtrl);
ng-annotate
Automatically add array style notations
Integrate into build process before minification
Can be easily integrated with Grunt, Gulp, Browserify, Rails Assets
Pipeline, and more
https://github.com/olov/ng-annotate
Controller Bloat
Limit Controllers to bartering
between view and data model
Data model should live in
provider (service, factory, etc.)
Controllers should have view-
model for data binding
Controller Bloat Example
deadbolt by Ed Carter
Chrome extension for hashing
passphrase to secure password
Very clean, readable code
Controllers get a little lengthy handling all
the user events
https://github.com/bittenbytailfly/deadbolt-
password-generator-chrome-
extension/blob/master/extension/js/control
lers.js
Service v Factory
Provider, Factory, Service, Value, Constant
All based on Provider
All singletons
Definitely over complicated
Read the docs: https://docs.angularjs.org/guide/providers
Value
Often used for storing primitives, e.g. key string values
var myApp = angular.module('myApp', []);
myApp.value('clientId', 'a12345654321x');
myApp.controller('DemoController', ['clientId', function DemoController(clientId) {
this.clientId = clientId;
}]);
Constant
Values available at config time and run time
Every AngularJS app has config phase, then run phase
myApp.constant('planetName', 'Greasy Giant');
Service
Returns new’d instance of object returned in service
Cannot create primitives
app.service('helloWorldService', function(){
this.hello = function() {
return "Hello World";
};
});
Note: Yes, we have called one of our service recipes 'Service'. We regret this and know that we'll be somehow punished for our misdeed. It's like we named one of our offspring 'Child'. Boy, that would mess with the teachers.
FactoryCan have dependencies
Can return primitives or functions
myApp.factory('apiToken', ['clientId', function apiTokenFactory(clientId) {
var encrypt = function(data1, data2) {
// NSA-proof encryption algorithm:
return (data1 + ':' + data2).toUpperCase();
};
var secret = window.localStorage.getItem('myApp.secret');
var apiToken = encrypt(clientId, secret);
return apiToken;
}]);
Provider
Closest to the metal
Must implement $get method
Available during config phase
Provider ExamplemyApp.provider('unicornLauncher', function UnicornLauncherProvider() {
var useTinfoilShielding = false;
this.useTinfoilShielding = function(value) {
useTinfoilShielding = !!value;
};
this.$get = ["apiToken", function unicornLauncherFactory(apiToken) {
return new UnicornLauncher(apiToken, useTinfoilShielding);
}];
});
myApp.config(["unicornLauncherProvider", function(unicornLauncherProvider) {
unicornLauncherProvider.useTinfoilShielding(true);
}]);
Provider Family Conclusion
The Mistakes
1. MVC Directory Structure
2. Modules
3.
4.
5.
6. Batarang
7. Too Many Watchers
8. Scoping $scope’s
9. Manual Testing
10. Using jQueryServices v Factory
Dependency Injection
Controllers Bloat
11. Memory Leaks
Controllers and Directives should subscribe to: $scope.$on('$destroy', …)
Remove handlers
Clean up resources which won’t be garbage collected automatically
MVC Directory Structuretemplates/
_login.html
_feed.html
app/
app.js
controllers/
LoginController.js
FeedController.js
directives/
FeedEntryDirective.js
services/
LoginService.js
FeedService.js
filters/
CapatalizeFilter.js
app/
app.js
Feed/
_feed.html
FeedController.js
FeedEntryDirective.js
FeedService.js
Login/
_login.html
LoginController.js
LoginService.js
Shared/
CapatalizeFilter.js
Modules
Group code into bundles which are independent
Directory structure should follow module design
Configure routes per module
Each module manages its own dependencies
Batarang
Still under active-isn development
Check out ng-inspector: http://ng-inspector.org/
Watchers
If something doesn’t change, don’t watch it
Bindonce directive is your friend
https://github.com/Pasvaz/bindonce
Scoping $scopes
Learn prototypical inheritance in javascript
http://www.airpair.com/javascript/workshops/javascript-prototypal-
inheritance
Don’t stress too much
2.0 is coming
Testing
Come back tomorrow
http://www.airpair.com/angularjs/
workshops/unit-testing-angularjs
Further Reading
Angular Best Practices: https://github.com/angular/angular.js/wiki/Best-
Practices
Officical App Structure Recommendation:
https://docs.google.com/document/d/1XXMvReO8-
Awi1EZXAXS4PzDzdNvV6pGcuaF4Q9821Es/pub
Angular 2.0 is coming!
Major changes in the pipeline
Goodbye Controllers, $scope, angular.module, jqLite
Rob Eisenberg goes in depth: http://eisenbergeffect.bluespire.com/all-
about-angular-2-0/
Igor Minar and Tobias Bosch overview:
https://docs.google.com/presentation/d/1XQP0_NTzCUcFweauLlkZpbbh
NVYbYy156oD--KLmXsk/edit#slide=id.g498335282_0112
Wrap Up
Reach me on twitter: @nuclearghost
Want individualized help?: http://airpair.me/NuclearGhost
Thanks for your time!
Top Related