| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
#Introduction
The goal of this style guide is to present a set of best practices and style guidelines for one AngularJS application. These best practices are collected from:
Note: this is still a draft of the style guide, its main goal is to be community-driven so filling the gaps will be greatly appreciated by the whole community.
In this style guide you won't find common guidelines for JavaScript development. Such can be found at:
For AngularJS development recommended is the Google's JavaScript style guide.
In AngularJS's GitHub wiki there is a similar section by ProLoser, you can check it here.
#Table of content
#General
Since a large AngularJS application has many components it's best to structure them in a directory hierarchy. There are two main approaches:
In this way the directory structure will look like:
. ├── app │ ├── app.js │ ├── controllers │ │ ├── page1 │ │ │ ├── FirstCtrl.js │ │ │ └── SecondCtrl.js │ │ └── page2 │ │ └── ThirdCtrl.js │ ├── directives │ │ ├── page1 │ │ │ └── directive1.js │ │ └── page2 │ │ ├── directive2.js │ │ └── directive3.js │ ├── filters │ │ ├── page1 │ │ └── page2 │ └── services │ ├── CommonService.js │ ├── cache │ │ ├── Cache1.js │ │ └── Cache2.js │ └── models │ ├── Model1.js │ └── Model2.js ├── lib └── test
Here is its layout:
. ├── app │ ├── app.js │ ├── common │ │ ├── controllers │ │ ├── directives │ │ ├── filters │ │ └── services │ ├── page1 │ │ ├── controllers │ │ │ ├── FirstCtrl.js │ │ │ └── SecondCtrl.js │ │ ├── directives │ │ │ └── directive1.js │ │ ├── filters │ │ │ ├── filter1.js │ │ │ └── filter2.js │ │ └── services │ │ ├── service1.js │ │ └── service2.js │ └── page2 │ ├── controllers │ │ └── ThirdCtrl.js │ ├── directives │ │ ├── directive2.js │ │ └── directive3.js │ ├── filters │ │ └── filter3.js │ └── services │ └── service3.js ├── lib └── test
When creating directive it might be useful to put all the associated to the given directive files (i.e. templates, CSS/SASS files, JavaScript) in a single folder. If you choose to use this style be consistent and use it everywhere along your project.
app
└── directives
├── directive1
│ ├── directive1.html
│ ├── directive1.js
│ └── directive1.sass
└── directive2
├── directive2.html
├── directive2.js
└── directive2.sass
This approach can be combined with both directory structures above.
One more slight variation of both directory structures is the one used in ng-boilerplate. In it the unit tests for given component are hold in the folder the component is located. This way when you make changes in given components it is easier to find their tests, the tests also act as documentation and show uses cases.
services
├── cache
│ ├── cache1.js
│ └── cache1.spec.js
└── models
├── model1.js
└── model1.spec.js
The app.js file contains routes definition, configuration and/or manual bootstrap (if required).
Each JavaScript file should only hold a single component. The file should be named with the component's name.
Use Angular project structure template like Yeoman, ng-boilerplate.
I prefer the first structure because it makes the common components easier to find.
Conventions about components naming can be found in each component section.
This will make your testing easier and in some cases prevent unexpected behaviour (for example, if you missed $scope.$apply in setTimeout).
Automate your workflow using tools like:
Use promises ($q) instead of callbacks. It will make your code look more elegant and clean, and save you from callback hell.
Use $resource instead of $http when possible. Higher level of abstraction saves you from redundancy.
Use an AngularJS pre-minifier (like ngmin or ng-annotate) for preventing problems after minification.
Don't use globals. Resolve all dependencies using Dependency Injection.
Do not pollute your $scope. Only add functions and variables that are being used in the templates.
Prefer the usage of controllers instead of ngInit. The only appropriate use of ngInit is for aliasing special properties of ngRepeat. Besides this case, you should use controllers rather than ngInit to initialize values on a scope.
#Modules
There are two common ways for structuring the modules:
Currently there's not a big difference, but the first way looks cleaner. Also, if lazy-loading modules is implemented (currently not in the AngularJS roadmap), it will improve the app's performance.
#Controllers
Do not manipulate DOM in your controllers. Use directives instead.
The naming of the controller is done using the controller's functionality (for example shopping cart, homepage, admin panel) and the substring Ctrl in the end. The controllers are named UpperCamelCase (HomePageCtrl, ShoppingCartCtrl, AdminPanelCtrl, etc.).
The controllers should not be defined as globals (no matter AngularJS allows this, it is a bad practice to pollute the global namespace).
Use array syntax for controller definitions:
module.controller('MyCtrl', ['dependency1', 'dependency2', ..., 'dependencyn', function (dependency1, dependency2, ..., dependencyn) {
//...body
}]);
Using this type of definition avoids problems with minification. You can automatically generate the array definition from standard one using tools like ng-annotate (and grunt task grunt-ng-annotate).
Use the original names of the controller's dependencies. This will help you produce more readable code:
module.controller('MyCtrl', ['$scope', function (s) {
//...body
}]);
is less readable than:
module.controller('MyCtrl', ['$scope', function ($scope) {
//...body
}]);
This especially applies to a file that has so much code that you'd need to scroll through. This would possibly cause you to forget which variable is tied to which dependency.
Make the controllers as lean as possible. Abstract commonly used functions into a service.
Communicate within different controllers using method invocation (possible when children wants to communicate with parent) or $emit, $broadcast and $on methods. The emitted and broadcasted messages should be kept to a minimum.
Make a list of all messages which are passed using $emit, $broadcast and manage it carefully because of name collisions and possible bugs.
When you need to format data encapsulate the formatting logic into a filter and declare it as dependency:
module.controller('myFormat', function () {
return function () {
//body...
};
});
module.controller('MyCtrl', ['$scope', 'myFormatFilter', function ($scope, myFormatFilter) {
//body...
}]);
#Directives
#Filters
#Services
#Templates
Use ng-bind or ng-cloak instead of simple {{ }} to prevent flashing content.
Avoid writing complex code in the template.
When you need to set the src of an image dynamically use ng-src instead of src with {{}} template.
Instead of using scope variable as string and using it with style attribute with {{ }}, use the directive ng-style with object-like parameters and scope variables as values:
...
$scope.divStyle = {
width: 200,
position: relative
};
...
<div ng-style="divStyle">my beautifully styled div which will work in IE</div>;
#Routing
| Back | FazBrowse Home | New Git URL |