Real Angular App Architecture
How To Keep It Simple But Powerful
Angular Is “Only” A Framework
• The way you organise your app is crucial
Module 1
Service A
Service B
Controller A
Controller B
Template A
Directive A
Directive B
…
Module 2
Service A
Service B
Controller A
Controller B
Template A
Directive A
Directive B
…
Module 3
Service A
Service B
Controller A
Controller B
Template A
Directive A
Directive B
…
…
Your App
Main Angular Building Parts -
Modules
• What it is: Definition of application part or feature bundle, it has module name and
dependencies array - angular.module(‘myModule’, [‘yourModule’,’theirModule’]);
• Do: Bundle controllers, directives, services, configs, etc… to one module, e.g.
markdown editor module - mdService, mdController, mdDirective
• Do: Usually one application can have more than 50 modules - included module
can be depended on another module, etc…
• Do: Use .config(…) to setup module on initialising or .run(…) on app starting
• Do: Lazy load whole modules include 3rd-party libs, implement something like
(https://github.com/ocombe/ocLazyLoad) to load .js files on demand when route
match
• Be Aware: Naming conflicts - AngularJS app has a single injector that holds
names for all objects without respect to module names, when two or more modules
has service, controller or directive with the same name, it will override it
Main Angular Building Parts -
Services
• What it is: Business logic holders, services are constructors or
singletons, there are 3 “almost same” types of services in angular
(service, factory, provider)
• Do: Let services hold complexity - make slim controllers and
directives
• Do: Reuse services by other services, controllers, directives,
configs, etc…
• Do: Wrap 3-rd party libraries into services, never reference globals
in angular, always use angular built-in dependency injection
• Don’t: Manipulate DOM elements inside services, only directives
should do it
Main Angular Building Parts -
Controllers
• What it is: Their purpose is to publish objects to $scope that is
used by templates to view and modify data
• Do: Make slim controllers, let services hold complexity
• Do: Use $scope events wisely, or don’t use it at all, services can
handle communication between controllers very well
• Do: For better performance, use $digest instead of $apply
($digest will do same as $apply but in current scope, not in
$rootScope)
• Don’t: Manipulate DOM elements inside controllers, only
directives should do it
Main Angular Building Parts -
Directives
• What it is: Repeated UI functionality wrappers, e.g. ng-repeat,
ng-model, dropdown, datepicker, or more complex like tree
views, etc…
• Do: Combine simple directives to build complex one, e.g.
dropdown+multi datepickers+multi timepickers
• Do: Manipulate DOM inside directive
• Do: Use $scope.$on(‘$destroy’, function(){ … }) to unbind all
listeners registered by directive to prevent memory leaks
• Don’t: Write large directives - split it to several small directives
by reusable behaviours
Main Angular Building Parts -
Templates
• What it is: HTML templates used by angular to generate DOM elements
• Do: Use one-time binding {{::mymodel}} in static data, such as localised
labels, for better performance
• Do: Sometimes is good idea to include template HTML in page, like <script
type=“text/ng-template” id=“mytemplate.html”> to avoid too many requests
• Do: Sometimes is good idea to define template in module .js file, like
angular bootstrap ui does (https://angular-ui.github.io/bootstrap/)
• Do: Keep templates readable - if they grow, try to wrap some parts into
directives
• Don’t: Write long expressions in attributes or brackets, try to wrap it into
$scope method instead
App Architecture Example
Angular $http
service
OfflineSync
service
Users Controller - publishing instances to template $scope
server
Grid Instance
(e.g. usersGrid)
Modal
Instance
QueryFilter
Instance
Tree
Instance
Main App Service
RestResource Instance (e.g. users)
Template - $scope methods DOM binding
ng-repeat=“user in
usersGrid.items”
ng-click= “usersGrid.
updateItem(user)”
{{user.name}} or ng-
model=“user.name”
Notifications
service StateService Instance (e.g. appState)
etc…
Loading Indicator
service
App Architecture Example
Angular $http
service
OfflineSync
service
Users Controller - publishing instances to template $scope
server
Grid Instance
(e.g. usersGrid)
Modal
Instance
QueryFilter
Instance
Tree
Instance
Main App Service
RestResource Instance (e.g. users)
Template - $scope methods DOM binding
ng-repeat=“user in
usersGrid.items”
ng-click= “usersGrid.
updateItem(user)”
{{user.name}} or ng-
model=“user.name”
Notifications
service StateService Instance (e.g. appState)
etc…
Loading Indicator
service
- Simple Loading Service used by
Loading Controller
- The only purpose is to view loading
icon and message to user if waiting for
server response
App Architecture Example
Angular $http
service
OfflineSync
service
Users Controller - publishing instances to template $scope
server
Grid Instance
(e.g. usersGrid)
Modal
Instance
QueryFilter
Instance
Tree
Instance
Main App Service
RestResource Instance (e.g. users)
Template - $scope methods DOM binding
ng-repeat=“user in
usersGrid.items”
ng-click= “usersGrid.
updateItem(user)”
{{user.name}} or ng-
model=“user.name”
Notifications
service StateService Instance (e.g. appState)
etc…
Loading Indicator
service
- Simple Notification Service used by
Notifications Controller
- The Only purpose is to view small
notification messages (info, warning,
danger, error, success)
App Architecture Example
Angular $http
service
OfflineSync
service
Users Controller - publishing instances to template $scope
server
Grid Instance
(e.g. usersGrid)
Modal
Instance
QueryFilter
Instance
Tree
Instance
Main App Service
RestResource Instance (e.g. users)
Template - $scope methods DOM binding
ng-repeat=“user in
usersGrid.items”
ng-click= “usersGrid.
updateItem(user)”
{{user.name}} or ng-
model=“user.name”
Notifications
service StateService Instance (e.g. appState)
etc…
Loading Indicator
service
- Data Buffer, if client is offline, it will
simulate $http service, but storing and
loading data in local DB
App Architecture Example
Angular $http
service
OfflineSync
service
Users Controller - publishing instances to template $scope
server
Grid Instance
(e.g. usersGrid)
Modal
Instance
QueryFilter
Instance
Tree
Instance
Main App Service
RestResource Instance (e.g. users)
Template - $scope methods DOM binding
ng-repeat=“user in
usersGrid.items”
ng-click= “usersGrid.
updateItem(user)”
{{user.name}} or ng-
model=“user.name”
Notifications
service StateService Instance (e.g. appState)
etc…
Loading Indicator
service
- Angular core service for handling
AJAX
App Architecture Example
Angular $http
service
OfflineSync
service
Users Controller - publishing instances to template $scope
server
Grid Instance
(e.g. usersGrid)
Modal
Instance
QueryFilter
Instance
Tree
Instance
Main App Service
RestResource Instance (e.g. users)
Template - $scope methods DOM binding
ng-repeat=“user in
usersGrid.items”
ng-click= “usersGrid.
updateItem(user)”
{{user.name}} or ng-
model=“user.name”
Notifications
service StateService Instance (e.g. appState)
etc…
Loading Indicator
service
- An instance of RestResource, it
provides a unified interface, other
services or controllers can easily get
info like pagination, list of items, etc…
- by default, there are methods like .find,
.one, .update, .create, .remove, but
can be configured to to handle any
other command
App Architecture Example
Angular $http
service
OfflineSync
service
Users Controller - publishing instances to template $scope
server
Grid Instance
(e.g. usersGrid)
Modal
Instance
QueryFilter
Instance
Tree
Instance
Main App Service
RestResource Instance (e.g. users)
Template - $scope methods DOM binding
ng-repeat=“user in
usersGrid.items”
ng-click= “usersGrid.
updateItem(user)”
{{user.name}} or ng-
model=“user.name”
Notifications
service StateService Instance (e.g. appState)
etc…
Loading Indicator
service
- It can store components state, e.g.
Grid instance filter query, sorting,
current page
- It can store and restore all states from
URL
- It can undo, redo states, so can be
used to undo whole page state
App Architecture Example
Angular $http
service
OfflineSync
service
Users Controller - publishing instances to template $scope
server
Grid Instance
(e.g. usersGrid)
Modal
Instance
QueryFilter
Instance
Tree
Instance
Main App Service
RestResource Instance (e.g. users)
Template - $scope methods DOM binding
ng-repeat=“user in
usersGrid.items”
ng-click= “usersGrid.
updateItem(user)”
{{user.name}} or ng-
model=“user.name”
Notifications
service StateService Instance (e.g. appState)
etc…
Loading Indicator
service
- UI component instances,
communicating via callbacks inside
controller - it is better than using
events
- In case there will be too many UI
component instances, you should split
controller and use service to
communicate between - but be aware of
too many components in one page, it is
not user friendly and will be slow
App Architecture Example
Angular $http
service
OfflineSync
service
Users Controller - publishing instances to template $scope
server
Grid Instance
(e.g. usersGrid)
Modal
Instance
QueryFilter
Instance
Tree
Instance
Main App Service
RestResource Instance (e.g. users)
Template - $scope methods DOM binding
ng-repeat=“user in
usersGrid.items”
ng-click= “usersGrid.
updateItem(user)”
{{user.name}} or ng-
model=“user.name”
Notifications
service StateService Instance (e.g. appState)
etc…
Loading Indicator
service
- Just simple pseudo example of usage
published $scope methods
Common Modules List
Example
• Rest Module - RestResource service, some request and response transformations
• Object Module - helper methods to manipulate object, such as deepGet, deepSet, objectToArray, etc…
• State Module - StateService and set of helpers
• Loading Module - loading indicator, and $http interceptors
• Notifications Module - simple messages
• Modals Module - modals management
• DragDrop Module - set of drag & drop directives and services
• ContentEditors Module - markdown, wysiwyg directives, parsing and generator services
• Localisation Module - simple localisation service, directives and filters
• Grid Module - grid behaviour service and directives
• Tree Module - tree view behaviour service and directives
• Query Module - advanced filter service and directives
• ocLazyLoad Module - https://github.com/ocombe/ocLazyLoad
• UIBootstrap Module - https://angular-ui.github.io/bootstrap/

Angular presentation

  • 1.
    Real Angular AppArchitecture How To Keep It Simple But Powerful
  • 2.
    Angular Is “Only”A Framework • The way you organise your app is crucial Module 1 Service A Service B Controller A Controller B Template A Directive A Directive B … Module 2 Service A Service B Controller A Controller B Template A Directive A Directive B … Module 3 Service A Service B Controller A Controller B Template A Directive A Directive B … … Your App
  • 3.
    Main Angular BuildingParts - Modules • What it is: Definition of application part or feature bundle, it has module name and dependencies array - angular.module(‘myModule’, [‘yourModule’,’theirModule’]); • Do: Bundle controllers, directives, services, configs, etc… to one module, e.g. markdown editor module - mdService, mdController, mdDirective • Do: Usually one application can have more than 50 modules - included module can be depended on another module, etc… • Do: Use .config(…) to setup module on initialising or .run(…) on app starting • Do: Lazy load whole modules include 3rd-party libs, implement something like (https://github.com/ocombe/ocLazyLoad) to load .js files on demand when route match • Be Aware: Naming conflicts - AngularJS app has a single injector that holds names for all objects without respect to module names, when two or more modules has service, controller or directive with the same name, it will override it
  • 4.
    Main Angular BuildingParts - Services • What it is: Business logic holders, services are constructors or singletons, there are 3 “almost same” types of services in angular (service, factory, provider) • Do: Let services hold complexity - make slim controllers and directives • Do: Reuse services by other services, controllers, directives, configs, etc… • Do: Wrap 3-rd party libraries into services, never reference globals in angular, always use angular built-in dependency injection • Don’t: Manipulate DOM elements inside services, only directives should do it
  • 5.
    Main Angular BuildingParts - Controllers • What it is: Their purpose is to publish objects to $scope that is used by templates to view and modify data • Do: Make slim controllers, let services hold complexity • Do: Use $scope events wisely, or don’t use it at all, services can handle communication between controllers very well • Do: For better performance, use $digest instead of $apply ($digest will do same as $apply but in current scope, not in $rootScope) • Don’t: Manipulate DOM elements inside controllers, only directives should do it
  • 6.
    Main Angular BuildingParts - Directives • What it is: Repeated UI functionality wrappers, e.g. ng-repeat, ng-model, dropdown, datepicker, or more complex like tree views, etc… • Do: Combine simple directives to build complex one, e.g. dropdown+multi datepickers+multi timepickers • Do: Manipulate DOM inside directive • Do: Use $scope.$on(‘$destroy’, function(){ … }) to unbind all listeners registered by directive to prevent memory leaks • Don’t: Write large directives - split it to several small directives by reusable behaviours
  • 7.
    Main Angular BuildingParts - Templates • What it is: HTML templates used by angular to generate DOM elements • Do: Use one-time binding {{::mymodel}} in static data, such as localised labels, for better performance • Do: Sometimes is good idea to include template HTML in page, like <script type=“text/ng-template” id=“mytemplate.html”> to avoid too many requests • Do: Sometimes is good idea to define template in module .js file, like angular bootstrap ui does (https://angular-ui.github.io/bootstrap/) • Do: Keep templates readable - if they grow, try to wrap some parts into directives • Don’t: Write long expressions in attributes or brackets, try to wrap it into $scope method instead
  • 8.
    App Architecture Example Angular$http service OfflineSync service Users Controller - publishing instances to template $scope server Grid Instance (e.g. usersGrid) Modal Instance QueryFilter Instance Tree Instance Main App Service RestResource Instance (e.g. users) Template - $scope methods DOM binding ng-repeat=“user in usersGrid.items” ng-click= “usersGrid. updateItem(user)” {{user.name}} or ng- model=“user.name” Notifications service StateService Instance (e.g. appState) etc… Loading Indicator service
  • 9.
    App Architecture Example Angular$http service OfflineSync service Users Controller - publishing instances to template $scope server Grid Instance (e.g. usersGrid) Modal Instance QueryFilter Instance Tree Instance Main App Service RestResource Instance (e.g. users) Template - $scope methods DOM binding ng-repeat=“user in usersGrid.items” ng-click= “usersGrid. updateItem(user)” {{user.name}} or ng- model=“user.name” Notifications service StateService Instance (e.g. appState) etc… Loading Indicator service - Simple Loading Service used by Loading Controller - The only purpose is to view loading icon and message to user if waiting for server response
  • 10.
    App Architecture Example Angular$http service OfflineSync service Users Controller - publishing instances to template $scope server Grid Instance (e.g. usersGrid) Modal Instance QueryFilter Instance Tree Instance Main App Service RestResource Instance (e.g. users) Template - $scope methods DOM binding ng-repeat=“user in usersGrid.items” ng-click= “usersGrid. updateItem(user)” {{user.name}} or ng- model=“user.name” Notifications service StateService Instance (e.g. appState) etc… Loading Indicator service - Simple Notification Service used by Notifications Controller - The Only purpose is to view small notification messages (info, warning, danger, error, success)
  • 11.
    App Architecture Example Angular$http service OfflineSync service Users Controller - publishing instances to template $scope server Grid Instance (e.g. usersGrid) Modal Instance QueryFilter Instance Tree Instance Main App Service RestResource Instance (e.g. users) Template - $scope methods DOM binding ng-repeat=“user in usersGrid.items” ng-click= “usersGrid. updateItem(user)” {{user.name}} or ng- model=“user.name” Notifications service StateService Instance (e.g. appState) etc… Loading Indicator service - Data Buffer, if client is offline, it will simulate $http service, but storing and loading data in local DB
  • 12.
    App Architecture Example Angular$http service OfflineSync service Users Controller - publishing instances to template $scope server Grid Instance (e.g. usersGrid) Modal Instance QueryFilter Instance Tree Instance Main App Service RestResource Instance (e.g. users) Template - $scope methods DOM binding ng-repeat=“user in usersGrid.items” ng-click= “usersGrid. updateItem(user)” {{user.name}} or ng- model=“user.name” Notifications service StateService Instance (e.g. appState) etc… Loading Indicator service - Angular core service for handling AJAX
  • 13.
    App Architecture Example Angular$http service OfflineSync service Users Controller - publishing instances to template $scope server Grid Instance (e.g. usersGrid) Modal Instance QueryFilter Instance Tree Instance Main App Service RestResource Instance (e.g. users) Template - $scope methods DOM binding ng-repeat=“user in usersGrid.items” ng-click= “usersGrid. updateItem(user)” {{user.name}} or ng- model=“user.name” Notifications service StateService Instance (e.g. appState) etc… Loading Indicator service - An instance of RestResource, it provides a unified interface, other services or controllers can easily get info like pagination, list of items, etc… - by default, there are methods like .find, .one, .update, .create, .remove, but can be configured to to handle any other command
  • 14.
    App Architecture Example Angular$http service OfflineSync service Users Controller - publishing instances to template $scope server Grid Instance (e.g. usersGrid) Modal Instance QueryFilter Instance Tree Instance Main App Service RestResource Instance (e.g. users) Template - $scope methods DOM binding ng-repeat=“user in usersGrid.items” ng-click= “usersGrid. updateItem(user)” {{user.name}} or ng- model=“user.name” Notifications service StateService Instance (e.g. appState) etc… Loading Indicator service - It can store components state, e.g. Grid instance filter query, sorting, current page - It can store and restore all states from URL - It can undo, redo states, so can be used to undo whole page state
  • 15.
    App Architecture Example Angular$http service OfflineSync service Users Controller - publishing instances to template $scope server Grid Instance (e.g. usersGrid) Modal Instance QueryFilter Instance Tree Instance Main App Service RestResource Instance (e.g. users) Template - $scope methods DOM binding ng-repeat=“user in usersGrid.items” ng-click= “usersGrid. updateItem(user)” {{user.name}} or ng- model=“user.name” Notifications service StateService Instance (e.g. appState) etc… Loading Indicator service - UI component instances, communicating via callbacks inside controller - it is better than using events - In case there will be too many UI component instances, you should split controller and use service to communicate between - but be aware of too many components in one page, it is not user friendly and will be slow
  • 16.
    App Architecture Example Angular$http service OfflineSync service Users Controller - publishing instances to template $scope server Grid Instance (e.g. usersGrid) Modal Instance QueryFilter Instance Tree Instance Main App Service RestResource Instance (e.g. users) Template - $scope methods DOM binding ng-repeat=“user in usersGrid.items” ng-click= “usersGrid. updateItem(user)” {{user.name}} or ng- model=“user.name” Notifications service StateService Instance (e.g. appState) etc… Loading Indicator service - Just simple pseudo example of usage published $scope methods
  • 17.
    Common Modules List Example •Rest Module - RestResource service, some request and response transformations • Object Module - helper methods to manipulate object, such as deepGet, deepSet, objectToArray, etc… • State Module - StateService and set of helpers • Loading Module - loading indicator, and $http interceptors • Notifications Module - simple messages • Modals Module - modals management • DragDrop Module - set of drag & drop directives and services • ContentEditors Module - markdown, wysiwyg directives, parsing and generator services • Localisation Module - simple localisation service, directives and filters • Grid Module - grid behaviour service and directives • Tree Module - tree view behaviour service and directives • Query Module - advanced filter service and directives • ocLazyLoad Module - https://github.com/ocombe/ocLazyLoad • UIBootstrap Module - https://angular-ui.github.io/bootstrap/