Angular.js Application Architecture – Setter – Lean Controller



Angular.js Application Architecture – Setter – Lean Controller

0 0


AngularArchitectureReveal

Presentation: Angular Application Architecture with reveal.js

On Github corymickelson / AngularArchitectureReveal

Angular.js Application Architecture

By Cory Mickelson

Resources

File Structure

Folder by Feature Structure
                /www
                    /app
                        /user
                            /user.module.js
                            /account.controller.js
                            /user.service.js
                            /account.html
                        /auth
                            /auth.module.js
                            /login.controller.js
                            /login.html
                        /map
                            /map.module.js
                            /map.controller.js
                            /map.service.js
                            /map.html
                        /configure
                            /configure.module.js
                            /configure.routes.js
                            /configure.run.js
                        /app.module.js
                    /sass
                    /js
                        /bundle.js
                    /index.html
            

Root Module

The Root Module pulls together all modules and features. Creating an application root module makes it very easy and simple to add and remove modules/features from your application

                //app.module.js
                
                    angular
                        .module('app', [
                            'app.config',
                            'app.user',
                            'app.map'
                    ]);
                
            

User Sub-Module

Create small modules that encapsulate one responsibility

                /www
                    /app
                        /user
                            /user.module.js
                            /account.controller.js
                            /user.service.js
                            /account.html
                
            

Setter

Set once Avoid using a variable for the module

                        //user.module.js
                        
                            angular
                                .module('app.user',['ui.router']);
                        
                    

Getter

More readable code, avoid variable collision

                        
                            angular
                                .module('app.user')
                                .factory('UserService', UserService);
                            function UserService(){...}
                        
                    
Named function reduces nested callback, are easier to debug, and more readable

Lean Controller

Defer logic in the controller by delegating to services and factories Logic may now be reused throughout application, and removes dependencies from controller

Controller

As you can see in this controller all logic is has been deferred to the factory: MapService, and UserService
                    
                        'use strict';

                        angular
                            .module('app.map')
                            .controller('MapController', MapController);

                        MapController.$inject = ['MapService', 'UserService'];

                        function MapController(MapService, UserService) {
                            var vm = this;
                            vm.markers = MapService.getMarkers();
                            vm.watch = watch;
                            vm.addMarker = addMarker;
                            var creator = UserService.getUid();

                            vm.location = {
                                creator: creator,
                                description: '',
                                name: '',
                                longitude: '',
                                latitude: ''
                            };

                            function watch() {
                                var watch = MapService.watchPosition();
                                watch.promise.then(function () {
                                }, function (err) {
                                     console.log(err);
                                }, function (data) {
                                    vm.location.latitude = data.coords.latitude;
                                    vm.location.longitude = data.coords.longitude;
                                });
                            }
                        }
                    
                

Factory

                    
                        angular
                            .module('app.map')
                            .factory('MapService', MapService);

                        MapService.$inject = ['FIREBASE_URL', '$firebase', '$cordovaGeolocation'];

                        function MapService(FIREBASE_URL, $firebase, $cordovaGeolocation) {
                            var markers = $firebase(FIREBASE_URL.child('web').child('cache')),

                            services = {
                                getPosition: getPosition,
                                watchPosition: watchPosition,
                                ref: ref,
                                bundle: bundle,
                                set: set,
                                getMarkers: getMarkers,
                                getMarker: getMarker,
                                deleteMarker: deleteMarker,
                                editMarker: editMarker
                            };

                            return services;

                            function getPosition() {
                                return $cordovaGeolocation.getCurrentPosition();
                            }

                            function watchPosition() {
                                var options = {
                                    enableHighAccuracy: true,
                                    frequency: 60000,
                                    timeout: 30000
                                };
                                return $cordovaGeolocation.watchPosition(options);
                            }
                        }
                    
                

Build Tools

  • Grunt
  • Gulp
  • Browserify

Grunt

Grunt is a javascript task runner. Grunt tasks are configured as JSON objects Angular build process using grunt

grunt concat grunt ngAnnotate grunt uglify
                    
                        module.exports = function (grunt) {
                            grunt.loadNpmTasks('grunt-contrib-uglify');
                            grunt.loadNpmTasks('grunt-contrib-watch');
                            grunt.loadNpmTasks('grunt-contrib-sass');
                            grunt.loadNpmTasks('grunt-contrib-connect');
                            grunt.loadNpmTasks('grunt-contrib-concat');
                            grunt.loadNpmTasks('grunt-ng-annotate');
                            grunt.loadNpmTasks('grunt-wiredep');
                            grunt.loadNpmTasks('grunt-contrib-clean');
                            grunt.loadNpmTasks('grunt-contrib-copy');
                    
                
                    
                        grunt.initConfig({

                            pkg: grunt.file.readJSON('package.json'),
                            ngAnnotate:{
                                app:{
                                    files:[{
                                        expand: true,
                                        src: ['_/js/scripts.js'],
                                        ext:'.annotate.js',
                                        extDot: 'last'
                                    }]
                                }
                            },
                            uglify: {
                                my_target: {
                                    files: {
                                    '_/js/scripts.js': ['_/components/js/app.js']
                                    }
                                }
                            },
                            concat:{
                                dist:{
                                src: ['_/components/js/app.js', '_/components/js/directives.js', '_/components/js/services.js',          '_/components/js/controllers.js'],
                                dest: '_/js/scripts.js'
                                }
                            },
                    
                
Wrap angular modules in an IIFE if concatenating

Gulp

Another javascript task runner, Gulp config files use javascript functions instead of JSON objects This example shows gulp with browserify

                    
                        gulp.task('browserify-watch', function () {
                            watch = true;
                            browserifyBundle();
                        });
                        function browserifyBundle(){
                        // you need to pass these three config option to browserify
                            var b = browserify({
                                cache: {},
                                packageCache: {},
                                fullPaths: true
                            });
                            b = watchify(b);
                            b.on('update', function(){
                                bundleShare(b);
                            });

                            b.add(sourceFile);
                            bundleShare(b);

                        }
                        function bundleShare(b) {
                            b.bundle()
                            .pipe(source(destFile))
                            .pipe(gulp.dest(destFolder));
                        }
                        ////////////////////////////////////////////////////////


                        gulp.task('watch',['browserify-watch'], function () {
                            gulp.watch(sassPaths.sass, ['sass']);

                        });
                    
                

The End

Questions?