AngularJS Best Practice Part 1: Project Layout and Coding Guidelines

Category:
Blog
Tags:
by Matt Calthrop May 28, 2024
Category:
Blog
Tags:
by Matt Calthrop May 28, 2024

Many, if not most, currently-available AngularJS code examples are simplified, and not implemented using best practice methods.This is understandable, in that the authors tend to want to keep the size of their examples to a minimum – however, this limits the scope of the usefulness of such examples when building a substantial web application.To fill this gap, we are building a publicly-available project that we will use to explore best practice approaches to architecting, developing and building an AngularJS web application.This project is a work in progress, and will therefore be part instruction, and part discovery.In this first post, we are looking at basic modularisation via project layout and coding guidelines.

Project Layout

Folder Structure

We’ll start with a useful way of structuring the directory hierarchy:/src

/css root directory for CSS

/main.less the master LESS file that loads required includes

/lib store any CSS libraries here

/lib-1 one directory for each CSS library

/vx.y.z store in version-numbered directory

/img root directory for images

/js root directory for JS

/components components the application uses

/common components that are used in different parts of the app

/directives custom directives – one dir for each directive

/filters filters – one dir for each filter

/app the code for the application proper

/pages contains code for each page – one dir for each page

/lib libraries used by the application

/lib-1 one directory for each JS library

/vx.y.z store in version-numbered directory

/test root directory for all test-related code

/config configuration files for testing

/mock mock data used in testing stored here

/unit unit tests

/components

/common follows structure of common source code

/directives ditto directives

/filters ditto filters

/app

/pages ditto pages

It’s worth noting that as an application grows in size, it may be necessary to change the directory structure to suit the coding needs.

Group files by component

You might have noticed in the directory structure above that there are no references to models, views or controllers: this is because we are grouping files by the component they belong to.Taking the About page as an example, we can see from the code repo that the following files are grouped together:/src/js/app/pages/about/

about-controller.js

about-data-service.js

about-main-view.html

about-model.js

about-wrapper-service.js

Coding Guidelines

Every file does one thing

It seems to be pretty common practice to lump a whole load of related, but separate, functionality into a single Javascript file.However, as all the JS files will be concatenated and minified into a single file at build time[1], it makes more sense to follow the convention of having a single file with a single responsibility.This is demonstrated in Group files by component, above.

Avoid the global namespace

Many code examples use constructs such as this:var myController = function($scope, …

// or

function MyController($scope, …

This results in a function or variable being stored in the global namespace, which we really want to avoid[2].The preferred way of implementing a Controller (for example), looks something like this:angular.module(

‘AboutControllerModule’,

[

]

)

.controller(

‘AboutController’,

[

‘$scope’,

‘MenuMainModel’,

‘AboutModel’,

function ($scope, MenuMainModel, AboutModel) {

$scope.aboutModel = AboutModel;

MenuMainModel.setCurrentMenuItemId(MenuMainModel.ABOUT);

}

]

);

The code above is a simplification of the Controller for the About page in our demo app.Note that we also avoid having to call Angular’s $inject method:MyController.$inject = [‘$scope’, …

Footnotes

[1]The build process will be covered a future blog post, but you can browse the Gruntfile here.

[2]In-depth discussion of why to avoid polluting the global namespace is outside the scope of this post – but there is plenty of information available on the web.

This blog is written exclusively by the OpenCredo team. We do not accept external contributions.