All Angular Services are singletons, using .service()
or .factory()
differs the way Objects are created.
Services: act as a constructor
function and are instantiated with the new
keyword. Use this
for public methods and variables
function SomeService () {
this.someMethod = function () {
};
}
angular
.module('app')
.service('SomeService', SomeService);
Factory: Business logic or provider modules, return an Object or closure
Always return a host Object instead of the revealing Module pattern due to the way Object references are bound and updated
function AnotherService () {
var AnotherService = {};
AnotherService.someValue = '';
AnotherService.someMethod = function () {
};
return AnotherService;
}
angular
.module('app')
.factory('AnotherService', AnotherService);
Why? : Primitive values cannot update alone using the revealing module pattern
Declaration restrictions: Only use custom element
and custom attribute
methods for declaring your Directives ({ restrict: 'EA' }
) depending on the Directive's role
<!-- avoid -->
<!-- directive: my-directive -->
<div class="my-directive"></div>
<!-- recommended -->
<my-directive></my-directive>
<div my-directive></div>
Comment and class name declarations are confusing and should be avoided. Comments do not play nicely with older versions of IE. Using an attribute is the safest method for browser coverage.
Templating: Use Array.join('')
for clean templating
// avoid
function someDirective () {
return {
template: '<div class="some-directive">' +
'<h1>My directive</h1>' +
'</div>'
};
}
// recommended
function someDirective () {
return {
template: [
'<div class="some-directive">',
'<h1>My directive</h1>',
'</div>'
].join('')
};
}
Why? : Improves readability as code can be indented properly, it also avoids the +
operator which is less clean and can lead to errors if used incorrectly to split lines
DOM manipulation: Takes place only inside Directives, never a controller/service
// avoid
function UploadCtrl () {
$('.dragzone').on('dragend', function () {
// handle drop functionality
});
}
angular
.module('app')
.controller('UploadCtrl', UploadCtrl);
// recommended
function dragUpload () {
return {
restrict: 'EA',
link: function (scope, element, attrs) {
element.on('dragend', function () {
// handle drop functionality
});
}
};
}
angular
.module('app')
.directive('dragUpload', dragUpload);
Naming conventions: Never ng-*
prefix custom directives, they might conflict future native directives
// avoid
// <div ng-upload></div>
function ngUpload () {
return {};
}
angular
.module('app')
.directive('ngUpload', ngUpload);
// recommended
// <div drag-upload></div>
function dragUpload () {
return {};
}
angular
.module('app')
.directive('dragUpload', dragUpload);
Directives and Filters are the only providers that have the first letter as lowercase; this is due to strict naming conventions in Directives. Angular hyphenates camelCase
, so dragUpload
will become <div drag-upload></div>
when used on an element.
controllerAs: Use the controllerAs
syntax inside Directives as well
// avoid
function dragUpload () {
return {
controller: function ($scope) {
}
};
}
angular
.module('app')
.directive('dragUpload', dragUpload);
// recommended
function dragUpload () {
return {
controllerAs: 'vm',
controller: function () {
}
};
}
angular
.module('app')
.directive('dragUpload', dragUpload);