AngularJS Workshop
JSFoo 2014
Shyam Seshadri
Most Important
• WIFI Network– HasGeek-Wifi (If you can see this)– HasGeek (Otherwise)
• WIFI password– geeksrus
• Open http://is.gd/ajs1day• Clone the repository locally• open the folder created, and run
– npm install
Introduction
• Ex Googler
• Author
– AngularJS for O’Reilly
– AngularJS Up & Running for O’Reilly
• Entrepreneur
• Coder / Geek
Agenda
• 1 day
• 4 Sessions
• Beginning to App in 16 Steps
• Hands on
• Questions? Try & save them for end of each session
Agenda (contd…)
Session 1
• Introduction & History
• Basic Concepts & Terminologies
• Working with Controllers
• Angular Services
• Working with AngularJSinbuilt services
Session 2
• Creating your own services
• Introduction to $http
• Promises in AngularJS
• Routing
Agenda (contd…)
Session 3
• Introduction to Testing in AngularJS
• Unit Testing in Angular
• End to End testing
Session 4
• Introduction to Directives
• Creating your own directives
• Best Practices
Requirements
1. NodeJS (http://nodejs.org)
2. Karma (npm install –g karma-cli)
3. Protractor (npm install –g protractor)
4. Webstorm(http://www.jetbrains.com/webstorm) -OPTIONAL
Github Repo
http://is.gd/ajs1day
Code Along – Initial Setup
Checkout:
git clone https://github.com/Fundoo-Solutions/angularjs-one-day.git
cd angularjs-one-day
Run:
npm install
Expectations
• You will not be an expert at the end!!
• Live, hands-on
– but as much as time permits
• Questions, as much as possible
• Touch upon each and every part of AngularJS
• Follow along as best
– Jump steps if falling behind
Expectations - continued
• One full app, from start to finish
– Simple, Todolist
– No Complex Directives
– No Login / Auth flows
• We will cover unit testing
– But gloss over end to end tests
• Try out things, break things
– That’s how we learn!
Suggestions
• Use Google Chrome
– Faster
– One of the best Web Development Tools
• If something doesn’t work
– Look at the console (in Development Tools)
– Look for typos
– Check against the next step
SESSION 1 – INTRODUCTION & BASICS
Agenda
• MVC & the Web
• Introducing AngularJS
• Basic Concepts
• Terminologies
• Working with Controllers
The Changing Web Paradigm
Complexity Shift
The need to manage complexity
Data Retrieval Biz. LogicAuthorization & Permissions
RenderingConcurrent
usageAnd so much
more
While hitting faster turnaround times
Feature 1
Deliver in 10 weeksFeature 2
Deliver in 2 weeksFeature 3
Deliver yesterday!!!
So how can we even attempt to do this?
The need for
• Structure
• Modularity
• Tests
• Speed of Development
Before AngularJS
• GWT – Do it all in Java
• jQuery + JS – Each project is different
• How do you test DOM manipulation?
• Dependent on Engineers, not on frameworks
Introducing .
• A MVC framework for the Web
• No need for a new templating language – uses HTML
• Two Way Databinding between View & Code
• Allows Reusable HTML components – Directives
• Separation of concerns
• Routing, Deep Linking, History
• Unit Testing framework built-in
The AngularJS MVC pattern
The Model is fetched and manipulated by the controller
Model gets rendered to the User as the View
User Actions in the view are triggered in the controller
Model
ControllerView
Model-V-C
A Simple Model in AngularJS
Just any JSON object returned by the Server
M-View-C
Projection of the Model
Template + Scope => View
Can be styled independently
Derives behavior from
Controller
M-V-Controller
The Controller is responsible for
Fetching data from the server
Exposing data to view
through Scope
Handling User
interactions like clicks
Any other biz. logic
Data Binding
jQuery only world
• <p id=“nameTxt”></p>
• $(‘#nameTxt’).text(nameVar);
• nameVar.onChange(function(newVal, oldVal) {// Update #nameTxt
});
• If an input field, then additional
• $(‘#nameInp’).change(function() {nameVar = $(‘#nameInp).val();
});
AngularJS world
• {{nameVar}}
• <input ng-model=“nameVar”>
Create your own components
jQuery only world
What if we could just do this?
<tabs>
<tab title=“Home”>content here</tab>
<tab title=“Contact”>content here</tab>
</tabs>
AngularJS world
Plus the content, and the logic ofSwitching between the tabs, and somuch more.
Routing
In JS, for deep linking, we need to:
• Have a state machine
• Have an allotted view which changes
• Manage addition and removal from history
• Attach the right controller and scope with each view
• Potentially load all content before displaying
All of that with a simple API, as part of ngRoute
Server communication
All the standards of $, plus
• Caching
• Configurability
• Resources
Define a Project as
• And then call
• Project.save()
• Project.delete()
• And more
Dependency Injection
•The concept of asking for dependencies, rather than creating them
•A Service / factory is responsible for creating and providing your dependencies (known as the injector)
What
•Testability
•Separation of concerns
•Declarative
•ReusabilityWhy
•Everywhere in AngularJS
•From Controllers to Services, from Directives to FiltersWhere
Dependency Injection
Testing
DO IT!
Testing
Unit Tests
• Test the individual functions
• Expected return values
• Side effects
• Focused, Specific
• Mocks out larger system behavior
Scenario Tests
• End to End
• Starts up a real browser
• Behaves like a user
• Can have a real server backing it
A Sample Unit test
Backend Requirements
• The same requirements that jQuery has– Nothing!
• Easier if it talks JSON– But not required
• Works well with Java, as well as with Ruby on Rails
• Needs a way of communicating to the server
• Concept of transforming requests and responses– No JSON? No problem!
Do I need to develop my entire app in AngularJS?
• Has the concept of ng-app
– Denote a section of the page
• Can integrate as a section in an existing app
• Can run it beside an existing app
– Some URLs handled by AngularJS
• Can expand over time, gradually
Who’s using AngularJS?
• Google (of course!)
– Double Click for Advertisers
– Youtube
– And many more
• Amazon
• Netflix
• ING
• Lots of startups
Future Plans
• Object.observable to replace dirty checking
• Web components / Shadow DOM integration
• Asynchronous Loading
• Http, Socket, Offline, much more
• Mobile first
AngularJS + Mobile
• <30 kb compressed & minified
• Optional ngTouch for Mobile
• Plays really well with Cordova / Phonegap
So how do we start?
• It all begins with the AngularJS library, and an ng-app
<html ng-app><head><script src=“angular.min.js”></script>
</head><body>
<input type=“text” ng-model=“name”><h1>Hello {{name}}</h1>
</body></html>
SESSION 1 CODE-ALONG STARTS NOW
Github Repo
http://is.gd/ajs1day
Code Along – Initial Setup
Checkout:
git clone https://github.com/Fundoo-Solutions/angularjs-one-day.git
cd angularjs-one-day
Run:
npm install
Code Along
Run:
node server.js
Open localhost:8000
Each Step
Step 0 - Open localhost:8000/step0/app
and so on…
At the beginning
• Static HTML
• Hardcoded data
• No functionality
Code Along – Session 1
• Hook up Angularstep1
• Controllers & Data bindingstep2
• More controllers & using Directivesstep3
• Forms and validationstep4
• Using AngularJS servicesstep5
Step 1 - Hooking up AngularJS
• In app.js, add,
– angular.module(‘todoApp’, []);
• In index.html, add
– ng-app=“todoApp”
• Try out AngularJS Expressions
– {{1 + 2}}
• Hiding the {{}} at load – ng-cloak
Pro-tip: Avoiding Flashing {{ }}
• Use the ng-cloak class
– Comes with angular.js
– Add it to your own css
• Use ng-bind
– Skips the find and replace step
Step 2 - Introducing AngularJS Controllers
• In sections/landing/landing-controller.js
• Refer to existing app– angular.module(‘todoApp’)
• Create controller– .controller(‘LandingCtrl’, [])
– Second argument array
– Save variables on this
• Ng-controller– As syntax
Step 2 - Data Binding at play (Display)
• {{ }}– Ng-bind alternative
• Can refer to functions, variables– Try it out
• Create this.firstTodo in LandingCtrl– {author: ‘Me’, title: ‘First todo’,completed: false,
dueOn: ‘17/9/2014’}
• Create var secondTodo in LandingCtrl– {author: ‘Me’, title: ‘Second todo’, completed:
true, dueOn: ‘17/9/2014’}
The Crazy AngularJS Controller / Service code
• angularModule.controller / service / factory / directive / filter
– First argument is the name
– Second argument an array
• Last argument of array is a function
• Every other argument is string with name of the dependency
• Function gets params injected as variables in same order
Step 3 - More controllers & data-binding
• Create an array of todos in LandingCtrl with
– author
– title
– completed
– dueOn
• Reuse data from previous step
Using common AngularJS directives
• Ng-repeat
– Over todos
• Ng-class
– Based on completed – fade out to grey if completed
– Create function getTodoClass in controller
– Takes a todo object as argument
– Returns object with class names as key, and boolean value
Step 4 - Forms and Validation
• In file app/sections/create-update-todo/create-controller.js
• Create a new controller (CreateCtrl)– Add self.todo, with completed false by default– Add function addTodo in it– Set self.message when triggered
• Add a form name• Use ng-submit to trigger a controller function• Use ng-model on input fields• Use ng-disabled on button with
formName.$invalid
Step 5 – Using core AngularJS services
• Add dependency as string in controller / service / factory / directive
• Add dependency in function arguments
• Use it!
– Show message using $window.alert
– Add dependency on $window in CreateCtrl
– Call $window.alert
AND BACK TO THEORY FOR A BIT
Concepts
• Scopes
• Directives
• Services
• Controllers
• Filters
• Partials
Terminology - Scopes
• It’s the context, stupid!
• Exposes model to the View
• Allows event propagation
• Options?
– Parent / Child
– Root
– Isolated
– None
Scope Hierarchy in our Application
$rootScope
LandingCtrl
RepeatItem1
RepeatItem1
CreateCtrl
Terminology - Directives
• Reusable Components
• Covered in Session 4
• Can have a template associated
• Behavior + Rendering
• Tabs
• Datepicker
• Thumbnail Widgets
Terminology - Services
• Behavior without a UI
• Biz. Logic shared across the app
• Application level Store!
• Think
– Server APIs
– Caches / Resources
– Factories
Terminology - Filters
• Formatting HTML content
• Can be chained with normal JSON objects
• Date Filter
• List Filter
Terminology - Controllers
• Business Logic backing the Views
• Usually a one to one association with a view
• Always linked to a view
• Exposes certain elements on the scope
Terminology - Partials
• A View without a context
• Combines with the scope to form the view
• Can be placed inside other views to create a composite view
Useful Inbuilt Services
• $http
• $resource
• $location
• $window
• $routeProvider
END OF SESSION 1
SESSION 2 – SERVICES, SERVERS & ROUTING
Agenda
• Creating our own services
• Intro to $http
• Promises
• Routing using ngRoute
What is an AngularJS Service
• Initialized once
• Returns function / object
• Guaranteed singleton for scope of application
Creating your own AngularJS service
• When should you create a service?
– Repeated Functionality
– State across the app
– Wrapping third party functionality
– Need something that can be intercepted / mocked
• And how?
Code Along – Session 2
•Create TodoService
•Use service across controllers
step6
Creating Services
• angular.factory(‘ServiceName’, [‘dep1’, ‘dep2’, function(dep1, dep2) {}])
• Function returns
– A function
– Or an object
• What is returned is the public API
Step 6 – Creating TodoService
• Create angular.factory TodoService
• Default array of todos (move from Ctrl)
• Functions
– query, returns array
– add: takes a todo, adds it to array
• LandingCtrl uses TodoService.query()
• CreateCtrl uses TodoService.add()
Factory vs Service vs Provider
• Factory– Function called
– Object / Function returned
• Service– new called on function provided
– OO paradigm
• Provider– Initial Config setup
– Most configurable
Using services as a store
• Singleton for the application
• Controllers created and destroyed as needed
• Singletons can be used for
– API
– Store
• Return an object with the API
• Any data in Service is available to another controller
Working with Servers
• $http
• ngResource
• Promises
Terminology - Promises
• JS is Asynchronous in Nature
• Can lead to the nested nightmare
• Instead, a promise is a simple API that allows you to chain asynchronous calls.
• Gives you the ability to wait for multiple asynchronous calls to finish without resorting to timeouts
• Common error handling!
Callback Hell
var currentProfile = null, username = 'something';
fetchServerConfig(function(serverConfig) {
fetchUserProfiles(serverConfig.USER_PROFILES,
username, function(profiles) {
currentProfile = profiles.currentProfile;
});
});
Promise Chaining
var currentProfile = fetchServerConfig().then(function(serverConfig) {
return fetchUserProfiles(serverConfig.USER_PROFILES, username);
}).then(function(profiles) {return profiles.currentProfile;
}, function(error) {// Handle errors in either fetchServerConfig or // fetchUserProfiles here
});
Working with servers - Options
$http
• Low Level
• Working directly with JSON
• Always interact with the service
• More control, more options
• Only way to talk JSONP
ngResource
• High Level
• Object representation of Server calls
• Easier to read and write
• Strict, expects server in a certain form
The core $http service
• GET
• POST
• DELETE
• PUT
• JSONP
Configuring the $http request
• Headers
• Caching
• Params
• Data
• Transformations
More hooks on the $http -Interceptors
• Common post return hook
• Recommended way of handling
– Errors & 404s
– Authorization
CODE-ALONG CONTINUES
Code Along – Session 3
•Fetch list of todosfrom server
•Post form data to server for create
step7
Fetching data from server
• $http service
• $http.get(url).then(function(response) {}, function(err) {});
• Ideally, wrap it in a TodoService for nicer API
• URL - /api/todo
Posting data to server
• $http.post(url, postData)
– Same .then
URL: /api/todo
DATA: todo JSON object
In TodoService
add: create: function(todo) {}
Refreshing the list of todos?
• Check out step7-events
• Scope events
• Can broadcast / listen for events using $scope
BACK TO THEORY FOR A BIT
Bookmarking in a Single Page App
In JS, for deep linking, we need to:
• Have a state machine
• Have an allotted view which changes
• Manage addition and removal from history
• Attach the right controller and scope with each view
• Potentially load all content before displaying
AngularJS routing
• $routeProvider Service
• Each route consists of
– A URL Regex
– A Template
– A Controller
– Other parameters
The ng-view
• The part of the single page app that responds to URL changes
• Associated with a single controller
• One ng-view per app only!
Handling route parameters
• Opening a list of recipes
• Opening a single recipe
• Declaratively declare them
– ‘/todo/:id’
• Now available as
– $routeParams.id
• Dependency Injection!
Avoiding partial loads – resolve
• An Empty UI while the server responds
• Broken styling / formatting due to lack of data
• Avoid it all with “resolve”
• What is Resolve?
– A series of promises
– Guaranteed to be resolved before the view is shown
– Passed in as parameters to the controller
SESSION 2 CODE-ALONG CONTINUES
Code Along – Session 2
•Templates added for routesstep8
•Add routes for create, update, and allstep9
Step 9 - Adding routes
• Include angular-route.js• Include ngRoute as a module dependency• Angular.module().config()• $routeProvider.when(url, configObj)• configObj Possible params
– templateUrl or template– controller– controllerAs– redirectTo– resolve
Step 9 – Reusing Templates
• Create vs Edit
• Same UI, different server calls
Step 9 – Other cool things
• Redirect user after adding / updating todo
• Add href links to navigate within application
– Add Todo
– Edit Todo
– Home Page
• ng-href vs href
– Also, ng-src vs src
BACK TO THEORY FOR A BIT
Authorization in SPAs
• Server side critical
– Session cookies
– Token based
• Client side
– Interceptors
– Resolves
– Cookies automatic
– Tokens, extra effort
Advanced $http
• Common Error Handling
• Request / Response transformations
• Extending $http
$http - Interceptors
• Request & Response interceptors
• Implement factory
– Return object with
• Request
• requestError
• Response
• responseError
A Sample Response Interception
.factory(‘myInt’, [‘$q’, function($q) {return {
response: function(resp) {return resp;
}, responseError: function(err) {if (canRecover(err)) { // Do Something }else { $q.reject(err); }
}};
});
$http – Request / Response Transformations
• transformRequest & transformResponse
– function()
– Global (config() section) or $http level
• Take data as a parameter
– Return response in needed format
END OF SESSION 2
SESSION 3 – TESTING
Agenda
• Automated Testing – what, why
• Unit testing
• Scenario Testing
Why should you unit test?
• You want to catch errors at the earliest possible time
• You want to ensure that you don’t end up breaking older features
• You don’t have a compiler to tell you when you make a typo
The 5 * 5 * 5 case
The Setup
• Server – 5 Flows
• Client – 5 Flows
• Client Input – 5 Flows
Testing it
• Manually– All possible permutations
– 5 * 5 * 5 = 125 tests to ensure all flows are tested
• Automated– Minimize smartly
– 5 tests for server
– 5 for client
– 5 for client input
– Another 5 – 10 end to end
– Total 20 – 25 tests
TDD and you
Test Driven Development, or TDD, is an AGILE methodology that flips the development lifecycle, by ensuring that tests are written first before the code is implemented, and that tests drive the development, and are not just used as a validation tool.
The tenets of TDD are simple:• Code is written only when there is a failing test that requires the
code to pass• Just the bare minimum amount of code is written to ensure that
the test passes• Duplication is removed at every step• Once all tests are passing, the next failing test is added for the next
required functionality.
TDD - Continued
These simple rules ensure that:
1. Your code develops organically, and that every line of code written is purposeful.
2. Your code remains highly modular, cohesive and reusable (as you need to be able to test it)
3. You provide a comprehensive array of tests to prevent future breakages and bugs
4. The tests also act as specification and thus documentation for future needs and changes.
Unit Testing in AngularJS world
• Jasmine (BDD Style)
• Declarative
• Reads like English
• Testacular for running tests
The Jasmine / BDD framework
describe("MyController:", function() {it("to work correctly", function() {
var a = 12;var b = a;
expect(a).toBe(b);expect(a).not.toBe(null);
});});
Dependency Injection in Tests
• Testing your TodoService?
beforeEach(inject(function(TodoService) {
}));
Want a $rootScope? Same way.
SESSION 3 CODE-ALONG STARTS NOW
Code Along – Initial Setup
Run:sudo npm install –g karma-cli
cd step10karma start
OR
cd step10
../node_modules/karma/bin/karma start
OR DO IT FROM WEBSTORM
Code Along – Session 3
• Left off from session 2step10
• Add a test for fetching todoliststep11
• Add a test for creating todostep12
Testing services
• beforeEach(module(ModuleName))
• beforeEach(inject(function(dep1, dep2) {}));
• Write your tests in each it block
Unit Testing controllers
• Ask for $controller service
• Create controller instance
– Pass in context specific dependencies
– Like $scope, $routeParams
Unit Testing with XHRs
• Ask for $httpBackend service
• $httpBackend.expectGET (or expectPOST)
• Provide expected URL
• .respond(responseData)
• Don’t forget the $httpBackend.flush() calls
• Don’t forget afterEach with– $httpBackend.verifyNoOutstandingExpectation()
– $httpBackend.verifyNoOutstandingRequest()
Step 11 – Testing LandingCtrl
• Create controller instance– $controller(‘LandingCtrl’)
• Set expectations using $httpBackend– expectGET
– respond
– Set expectation before request is made
• Remember, asynchronous!– When does the server respond?
– flush()
Step 12 – Testing CreateCtrl
• Create controller instance
• Setup todo object that will be created
– Where does it come from?
• When is the create request triggered?
– Set expectations before that
– expectPOST(url, data)
• What happens on success?
– Check redirect
AND BACK TO THEORY FOR A BIT
End to End testing
• Your unit tests pass
• Your business logic looks correct
• You have your routes setup
• Are you done?
• How do you know your application works?
Angular Protractor
• AngularJS Aware
– Grab the value of a binding
– Understand the ng-repeat
• WebDriver enabled
– No need for yet another runner
• Debugging capabilities
– Pause / Resume at will
Reduce the burden on manual QA
• Smoke Tests
• Build validation tests
• Run on every save?
• Catch breakages faster, fix faster
Installation
• npm install –g protractor
• webdriver-manager update
The configuration (conf.js)
// myConf.jsexports.config = {
seleniumAddress: 'http://localhost:4444/wd/hub',specs: ['e2eSpec.js'],jasmineNodeOpts: {
showColors: true},capabilities: {
browserName: ’firefox'},baseUrl: ‘http://localhost:8000’
}
Protractor – Writing Simple tests
• Add a simple configuration
– Point it to WebDriver and your tests
• Write the test
• Jasmine based
– browser.get('http://localhost:8000');
– browser.findElements(by.repeater(’todo in landingCtrl.todos'))
Protractor – Interacting with the UI
• AngularJS Aware
• Element
– By.binding
– by.model
– by.repeater
• Browser.debugger()
• Browser.takeScreenshot()
Running: Step by step
Install Webdriver (First time only):webdriver-manager update
Start Webdriver:webdriver-manager start
Start Server:node server.js
Start Protractor:cd test/e2eprotractor conf.js
END OF SESSION 3
SESSION 4 – DIRECTIVES & BEST PRACTICES
Agenda
• Directives
– Concepts
– Creating your own
• Best Practices
– Tools
– Project Structure
– Other Modules
Directives
• Reusable UI widgets
• Rendering + Behavior
• DOM Manipulation needed Directive
Ng-include
• A poor man’s directive
• Rendering, no behavior
• Dependent on context
SESSION 4 CODE-ALONG STARTS
Code Along – Session 4
•Extract out stock repeater
•Use ng-include to include rendering logic
step13
Step 13 – ng-include
• Extract out todo template into todo-widget.html
• Include it using ng-include
– Remember, ng-include expects a variable
– Use single quotes inside double quotes to tell it it is a string constant
Limitations of ng-include
• Expects each user to know name and path to the template
• Dependent on context
– Expects controller with functions to be defined
– Expects variables to be defined with certain names
• Not great for reusability
• Hard to make self-contained
The Two Types of Directives
Display Input
The Directive Life Cycle
• Directive Created
• Template Element Compiled
– Template Level Modifications done here
• Scope, Controller created
• Link Function
– Pre & Post linking (if children)
Understanding your options
• Scope
– Bindings
• restrict
• Template / Template URL
• Transclude
• Controller
• Compile / link
Restrict
• A Attribute <div my-dir></div>
• C Class <div class=“my-dir”></div
• E Element <my-dir></my-dir>
Scope
• False Default, shares parent scope
• True Creates a new scope
• {} isolated scope
– = binding -> Objects
– @ binding -> Attributes / Interpolated Strings
– & binding -> Functions
The Compile function
• DOM transformations
• Common to all instances of directive
– Think ng-repeat
– Think ng-view
• No Scope yet
The Linking Function
• Ability to add specific behavior
– When your directive is first loaded
– For future behavior, restricted to the element
• Run once for each instance of your element
Directive Controllers
• Controller functions for your directive
• Used for cross directive communication
• Use Link
– When you have functionality specific to your directive
• Use Controller
– When you have functionality that other directives (usually child) will need to access
Transclusions
• Customized content for directives
– Changes from usage to usage
• Think Tabs
• Think Zippy / Accordions
• Think Carousels
SESSION 4 CODE-ALONG CONTINUES
Code Along – Session 4
• Convert ng-include to directivestep14
• Convert directive to fully contained with data passed instep15
• Delete todo and reload liststep16
Step 14 - Converting ng-include to directive
• Create directive todoWidget
– Use as todo-widget in HTML
• Return Directive definition object
– Restrict: ‘A’
– templateUrl: ‘components/todo-widget/todo-widget.html’
Step 15 - Self contained directives
• Scope param
– ‘=‘ binding
– todo: ‘=todoData’
– Takes todo-data in HTML, saves it as $scope.todo
• Link function
– Gets three arguments - $scope, $element, $attrs
– getTodoClass function on $scope
Step 16 – Delete todo and reload list
• Add del function in todo-service– $http[“delete”](‘/api/todo’ + id);
• Add button in todo-widget.html– ng-click=“deleteTodo()”
• In directive– Add deleteTodo() function which calls service– Add whenDelete: ‘&’ in scope attribute– On success of service call, call $scope.whenDelete()
• In LandingCtrl– Add reload function– In HTML, add when-delete=“lCtrl.reload()”
BACK TO THEORY
BEST PRACTICES, MODULES, TOOLS
10 DOS AND 10 DON’TS IN ANGULARJS
DO #1: WRITE YOUR UNIT TESTS (AND SCENARIO TESTS)
DO #2: LEVERAGE DATA BINDING
DO #3: WRAP 3RD PARTY COMPONENTS AS DIRECTIVES / SERVICES
DO #4: USE MODULES & ORGANIZE CODE BY FUNCTIONALITY
DO #5: USE TRACK BY FOR NG-REPEAT
DO #6: NAMESPACE YOUR CODE
DO #7: USE MULTIPLE LAYERS FOR SERVICES
DO #8: MINIMIZE DATA ON SCOPE / THIS
DO #9: USE THE CONTROLLER AS SYNTAX
DO #10: USE RESOLVE FOR PRE-ROUTE CHECKS & INTERCEPTORS FOR ALL OTHERS
DON’T #1: USE $ROOTSCOPE AS A STORE. DON’T USE $SCOPE TO SHARE FUNCTIONS & VARIABLES
DON’T #2: DOM MANIPULATION IN CONTROLLER
DON’T #3: OVERUSE FILTERS IN YOUR HTML
DON’T #4: PUT DATA YOU DON’T SHOW ON SCOPE / THIS
DON’T #5: MANIPULATE THE UI DIRECTLY
DON’T #6: USE GLOBAL SELECTORS IN DIRECTIVES
DON’T #7: GO OVERBOARD WITH NG-REPEATS
DON’T #8: OVERUSE SCOPE EVENTS IN YOUR APPLICATION
DON’T #9: FORGET CLEANUP IN YOUR CONTROLLERS & DIRECTIVES
DON’T #10: CREATE GIANT FILES OR FOLDERS
Other modules
• Animation
• Touch
• Cookies
• Resource
• Security
• Routing
BEST PRACTICES
Directory Structure
• Yeoman / Angular – seed• App
– images– css– Vendors (libs)– sections– components
• Tests– Spec
• Mimic js folder structure
– E2e• Reflect app heirarchy
Modularizing your codebase
• What can be reused?
• What belongs in logical groups?
• Group by functionality, not by type
Build Process
• Grunt / Ant
• Glob / Minify your code base
• Load at the end of body
• Cache static files
– Namespace by version
– Use Etags
• ng-boilerplate is a great starting point
RequireJS
• Good
• Can be overkill
– Lot of extra boilerplate
• Great for lazy loading dependencies
• Beneficial only if you have hundreds of files
Dependency Injection
• Use it
• Depend on it
• Use the [] notation (more on this later)
• Capture external dependencies in Services
• Use Mocks to inject dependencies in tests
• Look at ng-annotate if you want to be lazy
3rd party callbacks & $apply
Do
• Use 3rd party libraries and components
• Integrate them as directives / services when possible
Don’t
• Forget to call $apply to let angular know when to do work
Handling Data & ACLs
• Resolve
– Load Data
– Handle auth checks
– Login or not?
• Interceptors
– Per request level
Flashing {{}} in HTML
• Use ng-cloak
• Use ng-bind instead of {{ }}
Syntax
• Use module. Syntax
• Use safe DI
• Namespace as much as possible
Putting things on $scope
• Minimize
• What the view needs only!
• The scope is heavy and expensive
• Every item gets digested and dirty checked
• Think twice, and thrice first
The $rootScope
DO NOT
• Use the root scope to store global state
• Use the root scope as a communication mechanism
• In fact, forget there is a parent $rootScope if at all possible
Valid Uses:
• Broadcasting and listening for events
Communicating in the App
• Services
• Scope $broadcast, $emit and $on
• URL Params
Attribute Directives
• You can create directives that are
– Attributes (like ng-show, ng-hide)
– Elements (<datepicker>)
– Classes (<div class=“autocomplete”>)
– Comments (<!– datepicker -->)
• But
– Always prefer to use attributes or classes
– IE compatibility issues!
Structuring Business Logic
Controllers• should not reference DOM• should have view behavior
– What should happen if user does X– Where do I get X from?
Services• should not reference DOM (mostly)• are singletons• have logic independent of view
– Do X operation
PS: Do put DOM manipulation in Directives
Using the [] for DI
myApp.controller(‘MyCtrl’, function($scope, $location) {});
Is the same as
myApp.controller(‘MyCtrl’, [‘$scope’, ‘$location’, function($scope, $loc) {}]);
Using the [] for DI
Until you compile your code!
myApp.controller(‘MyCtrl’, function(a, xy) {});
Is not the same as
myApp.controller(‘MyCtrl’, [‘$scope’, ‘$location’, function(a, xy) {}]);
[] notation is the only way AngularJS knows which params are which!
To $ or not to $
• $ is used by AngularJS internals only
– $scope
– $http
– $resource
• Don’t use $ when you are naming your own services, controllers, etc.
USEFUL TOOLS & LIBRARIES
Batarang
Karma + Webstorm
3rd Party Components
• Wijmo
• KendoUI
• Angular-UI
• ngModules.org
Other Tools
• Yeoman
• Ng-Boilerplate
SO IN SUMMARY…
Feedback
– Feedback?
– Comments?
– Suggestions?
• omniscient1 on Twitter
• Recommend us on LinkedIn (FundooSolutions) if you like it