AngularAtom—Component-based organization for AngularJS 1.x apps (Part 4)


December 13, 2014

Level 3 organization

Now we are ready to review the organization structure at the third level. If you’ve missed my previous posts, recommend reading them first before continuing further:

app/components/ folder

This folder contains all application components. A component is perceived as a single isolated feature or a single piece of application functionality. They are the building blocks of an app. Each application contains one or more components. Components are stateless and can be reused by other components. This is somewhat similar to the concept of features in Agile/XP methodology.

Examples of such components are:

  • auth—enables application to authenticate users (authn) and control their access (authz)
  • profile—enables profile management in an application
  • site-search—enables search within an application
  • dashboard—gives ability to users to manage application dashboard(s)

There is no hard set requirement on how you break down your app into components. A component may be a distinctive application feature, or it may be a UI widget, or a service that other components depend on. As long as they are stateless, reusable and compose your entire app functionality, the granularity at which you break your app into components is up to you to decide as an application designer. Any developer, looking inside the components/ directory should clearly see what functionality your application consists of.

  • [component-n]/—contains all resources necessary for this component to function. May contain sub-components. Sub-components are perceived as integral part of components and they do not create their own modules. Instead, they define their methods (controllers, directives, services etc.) on the parent component’s module itself.

  • helpers/—an optional component reserved for the helper utility functions usually implemented as pure functions. Alternatively, you may choose to create a separate component for each of these functions in lieu of the common helpers/ folder. Whatever works best from your app’s perspective.

app/layouts/ folder

This folder contains partial files individually describing each layout supported by the application. Layouts are injected into the main app/index.html by the abstract states. Your public section, for example, may inject one layout (ex. public.html) from the app.public abstract state, whilst the secure section may inject a completely different layout (ex. secure.html) from the app.secure abstract state.

Even if your application supports only one layout at the moment, I still recommend creating this folder and describing your single layout in default.html file. This is a very flexible approach that will allow you to additional layouts in the future, if needed.

app/states/ folder

This folder contains a hierarchy of all application UI states. A state corresponds to a “place” in the application in terms of the overall UI and navigation. A state describes (via the controller/template and view properties) what the UI looks like and does at that place. Your application UI can transition from one state to another when certain event is triggered. UI can be in only one state at a time (a.k.a current state), but child state still activates its parents. Read more on states

I strongly recommend creating a UI state diagram prior to coding states. The directory structure inside your app/states/ folder will mimic the hierarchy of that UI state diagram. Any developer, looking inside the states/ directory should get a clear idea what UI states your application supports.

  • [ui-state-n]/—contains necessary UI resources (e.g. ui-view templates, ui-view controllers, images, CSS etc.) to render this particular UI state. Each state may contain one or more child states that, unlike sub-components, each define their own module. This is because each state, be it parent or child, is looked at as an independent citizen that can be added or removed at any time of the application lifecycle.

Unit tests

Unit tests are suffixed with .spec.js and placed alongside each file they are testing. There is no separate folder for the unit tests. This is done intentionally, so it is easier to locate the existing and/or missing unit test for any given file.

I recommend Mocha framework with Chai assertion library for writing all of your unit tests. This library has great support on the NodeJS server side as well. Keep your code across frontend and backend as consistent as possible.

Conclusion

This concludes my posts on the “AngularAtom—the component-based organization of AngularJS 1.x apps” topic. The entire component-based organization directory structure can be viewed in the “tl;dr” section of the introduction post. Make sure to check out the original AngularJS PhoneCat app converted to the new AngularAtom component-based structure.

I hope you found this useful in organizing your Angular 1.x apps. I may be making further updates to this organization structure based on the feedback I get, so please make sure to share your thoughts in the comments below.


Today my environment was:

  • Angular 1.3.5
  • AngularUI Router 0.2.12
  • Mac OS X 10.10.1