General Guidelines
John Papa’s Angular Style Guide should be used as the basis for our Angular conventions. Todd Motto’s style guide is mostly the same as John Papa’s, but includes some additional tips.
Third-party resources that are not Banno-specific but generally offer good advice:
File Format
It is recommended to specify an .editorconfig file for each project and use an editor plugin to automate the formatting (see the sample project file and sample front-end library file). The EditorConfig website has more information and plugins for popular editors.
Files should be saved as UTF-8 with Unix line endings.
Why? UTF-8 is the most compatible encoding across editors, browsers, and other clients.
Spaces should be used for indentation, usually at 2 spaces per indent.
Why? A convention needs to be set, and this is preferred by the majority of developers (both in the JavaScript team, and the Banno organization and community at large). Spaces also work/look better across a variety of environments. But as long as project defines an
.editorconfig, it doesn’t really matter what style is used.
Filesystem Structure
File names should be in all lowercase, using hyphens to separate words. Periods are used for nested extensions or typing (e.g.,
file.min.jsorfeature.directive.js).Why? All-lowercase prevents issues when using them on filesystems that don’t strictly distinguish case (Windows, OSX).
Why? Hyphens are the preferred separator in URL paths, so use them in the filesystem too.
Source code should be contained in
srcfolder and organized according to John Papa’s Application Structure guidelines. For example:[src] [feature-name] example of feature folder feature-name.css feature-specific CSS feature-name.directive.js directive feature-name.html directive's partial [filters] project-wide filters [layout] container/page/overview components [services] project-wide services app.config.js Angular config() blocks, and similar startup config app.constants.js Angular constant() blocks, either immutable project values or vendor globals app.mocks.js Mocks and other code used only during development app.module.js Angular module definition app.routes.js Routing definitionsAn
app.module.jsshould always exist in Angular projects; don’t name itapp.jsormodule.js, even if there is only 1 module. If there are multiple modules, use an appropriate prefix for each one.Why? Always using the same prefix & name for the main module makes it easy to find and prevents future renaming if additional modules are added.
Contrary to John Papa’s guidelines on organizing tests, tests should be separated from source code in a
testfolder:[test] [e2e] end-to-end tests protractor.conf.js Protractor config workflow1.spec.js test suite workflow2.spec.js [unit] unit tests feature-name.directive.spec.js test suite karma.conf.js Karma config requirejs.conf.js RequireJS configIf there are no E2E tests (e.g., the project is an API library), then all the files can be kept in the
testroot folder, without aunitsubfolder.Why? Traditionally (with Banno and the developer community), tests are kept in a separate folder.
Why? We also typically have E2E tests, which don’t follow the one-to-one file ratio of unit tests.
Naming
In general, variable names should be camel-cased.
Example:
var eachWordExceptFirstIsCapitalized = true;Example:
var acronymsLikeJsAreAlsoCamelCased = true;Why? A convention needs to be set, and this is the most common practice in the Javascript community.
Constructors (function intended to be invoked with
new) – which includes Angular services – should begin with a capital.Example:
```javascript function Person() { this.name = 'John'; } var person = new Person(); ```Why? Capitalizing the name indicates at a glance that the function is intended to be used as a constructor.
Variables that should not be changed can be written in
UPPER_CASE_WITH_UNDERSCORES. But whenever possible, theconstkeyword should be used instead.Example:
var DONT_CHANGE_ME = 'some value';Why? Until ES6 is widely used, this naming style indicates that the variable’s value should not be changed.
Angular components (services, constants, values, directives, etc.) must be given unique names. Ideally they should be universally unique, but at the very least they should be unique to the Banno ecosystem. A project prefix is usually a good idea (e.g.
sentrySomeServiceandmobileSomeService).Why? Angular’s module system does not use namespacing, so if 2 modules each have a component with the same name, one of them will be replaced by the other.
Angular Modules
Angular modules should be named
banno.projectName, whereprojectNameis a short, camel-cased name of the project. Related projects that encompass multiple modules can use “submodules” – for example,banno.sentry.apiandbanno.sentry.ui.Example:
angular.module('banno.session', []);Why? Modules should have a namespace prefix (here
banno) to prevent naming conflicts.Why? Separating names with periods seems to be the most common practice in the Angular community.
If you have multiple modules defined in a project, consider splitting them out into separate projects, especially if they are reusable.
Angular Dependency Injection
Use a build tool such as ng-annotate to automatically annotate the dependencies for minification-safe code.
Example:
/** @ngInject */ function AvengersController(storage, avengerService) { /* ... */ }Why? Manually annotating the code requires duplication of the dependencies in the code – more typing and more chance of error.
Directives
Use isolate scope if a directive is considered a self-contained component/widget. This is accomplished by explicitly setting the
scopeproperty to the desired local bindings. Isolate scope can be accessed in unit tests with theisolateScope()method.Do not use isolate scope if the directive simply decorates an element with a extra styling or functionality (e.g. a directive for the
<a>tag). In these cases isolate scope is more likely to conflict with other directives.
Testing
Check out our testing guidelines & tips page for details.
Contrary to John Papa’s guidelines on stubbing and spying, we do not use Sinon (though you are free to use it in a project if you wish).
Why? Jasmine’s spies usually have the functionality that we need, and Sinon has never been part of our process.
Linting
Use ux-lint to lint your code.
Why? ux-lint provides the same linting as ESLint, JSHint, and JSCS, but uses the Banno JS settings by default.