Top Banner
FROM SCRATCH! github.com/xmlilley/ng-demos @ Angular Meetup DC, 11/13/13 by: Christian Lilley about.me/XML @XMLilley Friday, November 15, 13
131

Angular from Scratch

Jan 27, 2015

Download

Technology

A two-hour introduction to AngularJS, delivered at the Angular Meetup DC, on 11/13/13. Demo files available at https://github.com/xmlilley/ng-demos
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Angular from Scratch

FROM SCRATCH!

github.com/xmlilley/ng-demos

@ Angular Meetup DC, 11/13/13

by: Christian Lilleyabout.me/XML @XMLilley

Friday, November 15, 13

Page 2: Angular from Scratch

GOALS & ASSUMPTIONS• We’re all familiar with basic Javascript & HTML & MVC

terminology, but maybe not Angular’s take on it.

• Yeoman is awesome. But the Yeoman way and the basic (naïve) way aren’t really compatible in a 2-hr session. We’ll leave Yeoman for another day.

• I wish there was more time for audience hands-on tonight, but Angular’s a big topic. So, all the demo code is available for take-home experimentation.

• Save questions for breaks & the end, pls. I’ll stick around.

Friday, November 15, 13

Page 3: Angular from Scratch

ANGULAR BUZZWORDS• Full Application Framework,

not a Library• MV*• Convenient Abstractions• Total Modularity, Reusability• Pub-Sub Communications

Between Modules• Dependency Injection• Routing, Deep-Linking, History• Filters, Expression Interpolation

• Data-Binding• HTML Templating• Testing Baked-In (Karma)• Integrated Promises ($Q)• Localization• Form Validation• “Big UI”• MIT License

Friday, November 15, 13

Page 4: Angular from Scratch

ANGULAR IS ALL ABOUT...• MV*: A data model, templates for viewing/interacting with it,

and logic in controllers, services, directives, etc. • Declarative Behavior: Protect Extend HTML. HTML is

right for templates, not JS. Intentions are visible in templates.

• Data-Binding: User or Program can modify the model, and views update automagically to reflect those changes.

• Model-Driven Behavior: DOM / View updates based on model, not brittle imperative logic. Truth in DOM Model.

• Modular Architecture, Separated Concerns: DOM changes in Directives, model changes in Controllers, abstracted app-wide support functions & data in Services

Friday, November 15, 13

Page 5: Angular from Scratch

Let’s get started!

Friday, November 15, 13

Page 6: Angular from Scratch

Friday, November 15, 13

Page 7: Angular from Scratch

BootstrappingYour App

The ng-app directive tells Angular what part of your main template it needs to watch. It ‘wakes up’ Angular.

You can (should) define a specific Angular module to serve as the core app logic: ng-app=‘myModule’

You can also bootstrap manually, if you need to.

Friday, November 15, 13

Page 8: Angular from Scratch

Data-BindingAngular’s declarative 2-way data-binding is part of its special sauce.

Changing data in the model automagically updates the view. Changing data in the view automagically updates the model.

model -> view -> model -> view

LET ANGULAR DO THIS FOR YOU! It’s part of Angular’s emphasis on model-driven UI.

Friday, November 15, 13

Page 9: Angular from Scratch

DOM

MODEL

Angular watches for changes here

Updates the model

accordingly

Consequent model changes by Angular

Then shows final outcome in the DOM

Model Changes can

start anywhere

Don’t do imperative DOM

Changes!

Truth lives Here! Not in DOM!

Friday, November 15, 13

Page 10: Angular from Scratch

Tells Angular: “Watch this space”

Tells Angular: “Bind this input.”

Tells Angular: “Insert Data here.”

Friday, November 15, 13

Page 11: Angular from Scratch

But what about those curly-brackets?

ANGULAR EXPRESSIONS

Friday, November 15, 13

Page 12: Angular from Scratch

With an Angular Expression, You Can:

Do math, or comparison

Concatenate text

Reference a model property

Invoke a function

But not: Control Flow, like conditions or loops (app logic belongs in controllers)

Friday, November 15, 13

Page 13: Angular from Scratch

One more thing you can do:

Filter the output of the expression

Filters are applied by ‘piping’ an expression into one:

{{modelName.propertyName  |  filterName:arg}}

Friday, November 15, 13

Page 14: Angular from Scratch

DEMO DEMO DEMO

Friday, November 15, 13

Page 15: Angular from Scratch

So, How Can we Build a More Complicated

App Than This?

Organize code withMODULES

Friday, November 15, 13

Page 16: Angular from Scratch

Modules are where we put our code: like filters, controllers, directives, services, and configuration information.

They provide us with encapsulation and re-usability for macro-level groupings of code.

Note that angular.module(‘moduleName’) is both a creator and a retriever.

Friday, November 15, 13

Page 17: Angular from Scratch

And when we want to organize our data

(view-models), too?

Organize view data & functions with

CONTROLLERSFriday, November 15, 13

Page 18: Angular from Scratch

Controllers IntroControllers are function Instances, used for interacting w/ data in views:

They’re created and destroyed along with elements/templates.multiple invocations = multiple instancesIf you want persistence, either place on an element that’s persistent, or place the data/methods in a service (more later).Hard to address a *specific* controller, so use events for communication (more later).

Friday, November 15, 13

Page 19: Angular from Scratch

DEMO DEMO DEMO

Friday, November 15, 13

Page 20: Angular from Scratch

Services IntroServices are ludicrously simple:

Remember (from, like, 1 slide ago), how controllers are created and destroyed every time you need one? And there can be lots of instances of a single controller type?

Services, by contrast, are unicorns, and last forever. (jargon: ‘lazy-loaded singletons’)

Friday, November 15, 13

Page 21: Angular from Scratch

Templates/Views IntroIn Angular, HTML is the template language!

Use inline HTML, external files, or simple strings as templates.

Then use expressions (and directives) to insert data from your model into the view.

Re-use templates with different controllers, re-use controllers with different templates.

Friday, November 15, 13

Page 22: Angular from Scratch

DEMO DEMO DEMO

Friday, November 15, 13

Page 23: Angular from Scratch

Routing IntroSince we’re extending HTML in our templates, let’s extend the browser too.

Routing lets you drive your interface views using the content of the location/URL bar.

This lets our Angular Apps behave just like the server-side apps that users are used to, with forward/back and deep-linking to specific content.

Friday, November 15, 13

Page 24: Angular from Scratch

DEMO DEMO DEMO

Friday, November 15, 13

Page 25: Angular from Scratch

Directives IntroControllers are just for data interactions. So DOM code has to go somewhere. Directives it is.

Modular, re-usable, de-coupled DOM logic. Directives embody all of Angular’s major design principles.

Way easier to use than the (old) Angular docs make it seem. We’ll have you writing your own in no time.

Friday, November 15, 13

Page 26: Angular from Scratch

Directive Pop-Star:NG-REPEAT

Everybody digs it: throw a series of data into your view super-easily.

Like ‘collection-views’ in other libraries

filter/sort the output if you like

Friday, November 15, 13

Page 27: Angular from Scratch

DEMO DEMO DEMO

Friday, November 15, 13

Page 28: Angular from Scratch

Coming up... the DEETS

First... Questions?

Friday, November 15, 13

Page 29: Angular from Scratch

CONTROLLERSIn (a smidge more) Detail

Friday, November 15, 13

Page 30: Angular from Scratch

About ControllersBest-practice: use controller only for dealing with data/model. Let directives handle updating the views based on the properties of the model.

Two ways to define:

using .controller() method on a module

As an ordinary named function(This will wind up on global scope. No good reason to do this. Just recognize it if you see it.)

Friday, November 15, 13

Page 31: Angular from Scratch

TEMPLATES/VIEWSIn Detail

Friday, November 15, 13

Page 32: Angular from Scratch

Templates DemoNote: when we provide the name of a template in the declaration of a directive like ng-include, we have to wrap it in a second pair of quotes.

The first pair of quotes delimits an expression, which will be eval()’d by Angular. Since we supply a template path as a string, it needs the quotes. We could also reference a property on the model, without needing to do that.

Friday, November 15, 13

Page 33: Angular from Scratch

Templates/ViewsWe can include templates conditionally, using directives like ng-show/ng-hide, ng-if, ng-switch

(We’ll also demonstrate how to use custom directives as another way to include a template.)

But the most powerful way to conditionally show content, is to use the browser’s address bar. Which means we want...

Friday, November 15, 13

Page 34: Angular from Scratch

Templates SNAFUBrowsers don’t like to let you access external local files. This sets off ‘same-origin’ errors. Simple solution: start a server. Painless Javascript/Node approach:

But, no logging!

‘Ole-reliable Python option with logging:

Or, the faster ‘Twisted’ (comes w/ OSX):

>>  sudo  npm  install  -­‐g  http-­‐server>>  http-­‐server  (or:  `node  bin/http-­‐server`)

>>  python  -­‐m  SimpleHTTPServer  8000

>>  twistd  -­‐no  web  -­‐-­‐path=.

Friday, November 15, 13

Page 35: Angular from Scratch

Templates SNAFU

Or, you can just use Yeoman/Grunt:

(do this)

>>  grunt  server

Friday, November 15, 13

Page 36: Angular from Scratch

ROUTINGIn Detail

Friday, November 15, 13

Page 37: Angular from Scratch

First: $locationAngular’s $location service is bound to window.location (ie. to what’s in the browser’s ‘address bar’)

Changes to the URL in the address bar are reflected in $location & changes to $location are reflected in address bar.

‘Back’ & ‘Forward’ are supported, as is deep-linking

See: “Using $location” guideFriday, November 15, 13

Page 38: Angular from Scratch

$routeThe $route service (configured via $routeProvider) gives us the ability to react programmatically to changes in the $location (plus $routeParams).

We specify a template that will be rendered inside an <ng-view> in response to a given route-change, along with its controller and some other details.

Friday, November 15, 13

Page 39: Angular from Scratch

Routing Is A Config For Your App ModuleFundamentally, routing works as a configuration detail on your base application module. (The one in ng-app.)

There are two ways to configure your app: by supplying a config function at module creation, or by invoking the config function on your app after creation...

Friday, November 15, 13

Page 40: Angular from Scratch

2 Ways to Config AppA config function is the (unpopular) third argument to a module’s creation:

Or, after the fact w/ Module.config( )

myModule = angular.module(name, [dependencies], function(injectables) { // Configuration details, like routing});

myModule.config(function(injectables) { // Configuration details, like routing});

Friday, November 15, 13

Page 41: Angular from Scratch

Routing SyntaxRoutes are added via configuration methods called on $routeProvider in the app config function.

There are only two basic methods involved:

$routeProvider.when(path, route)

$routeProvider.otherwise(params)

Friday, November 15, 13

Page 42: Angular from Scratch

Route Config ObjectWe can include an optional route config object for each path, with the following options:

template: html template as stringtemplateUrl: path to a partialcontroller: binds an instance of specified controller to the template instanceredirectTo: a path string or a function that returns one resolve: a function or service reference that will execute (or promise that resolves) before $routeChangeSuccess

Friday, November 15, 13

Page 43: Angular from Scratch

Routing ExamplemyModule.config(function($routeProvider) { $routeProvider .when('/home', { templateUrl: 'home.html', controller: homeCtrl }) .when('/index', { redirectTo: '/home’ }) .when('/archive/doc/:docId', { templateUrl: 'archive_doc.html', controller: archCtrl }) .when('/contact', { templateUrl: 'poc.html', controller: pocCtrl, resolve: { // I will cause a 1 second delay delay: function($q, $timeout) { var delay = $q.defer(); $timeout(delay.resolve, 1000); return delay.promise; }}) .otherwise({ redirectTo: '/home' });});

Friday, November 15, 13

Page 44: Angular from Scratch

.otherwise()

myModule.config(function($routeProvider) { $routeProvider .when('/home', { templateUrl: 'home.html', controller: homeCtrl }) .otherwise({ redirectTo: '/home' });});

The only property in the .otherwise() config object is redirectTo

NOTE: the value of redirectTo should be a path, like ‘/home’, not a template location like ‘home.html’. The route for ‘/home’ will then take care of supplying the template.

Friday, November 15, 13

Page 45: Angular from Scratch

Named Groups in PathThe path can contain ‘named groups’ starting with a colon (/path/path/:name).

All characters between colon and next slash are matched and stored in $routeParams.

From $routeParams, you can access that data and use it in preparing the view, based on related data.

Good technique for dynamically including data from a collection: users, products, chapters, etc.

Friday, November 15, 13

Page 46: Angular from Scratch

Named Groups in Pathexample definition from Angular docs:

Example URL:

The Route Params you’ll see for that:

$routeProvider.when('/Book/:bookId/ch/:chapterId', {templateUrl: 'chapter.html',controller: ChapterCntl});

//docs.angular.org/Book/Gatsby/ch/4

$routeParams = {"bookId":"Moby","chapterId":"1"}

Friday, November 15, 13

Page 47: Angular from Scratch

$scope & Models In Detail

Friday, November 15, 13

Page 48: Angular from Scratch

‘Models’Unlike Ember, Angular doesn’t force you into creating OOP models using their abstractions. Do as you like.

But model data should reside in objects that are properties on the $scope (‘model objects’, if you will), not directly in properties of the scope. Operations upon properties stored directly on $scope can have unexpected results. This is *totally* undocumented, but comes from Angular core team.

Friday, November 15, 13

Page 49: Angular from Scratch

WTF is $scope ???So, if Angular models are just plain-old Javascript objects (POJOs), what do we need this $scope thing for?Dependency InjectionAngular will use DI to make sure that the correct, contextual data is where you need it: in re-usable controllers, directives & views.$scope also gives us inheritance, via a DOM-like tree. Data available to app root is also available on leaves.

Friday, November 15, 13

Page 50: Angular from Scratch

$rootScope

Main/Nav Controller

$scope

View 1 Controller

$scope

View 2 Controller

$scope

Directive A-1$scope

Directive B$scope

Directive A-2$scope

Directive C$scope

Directive C can access all

properties from all three parent

scopes

Friday, November 15, 13

Page 51: Angular from Scratch

Visualizing Scope

Use the Angular Batarang!!!

Friday, November 15, 13

Page 52: Angular from Scratch

SERVICESIn Detail

Friday, November 15, 13

Page 53: Angular from Scratch

Services in Detail:Why Services?

Provide re-usable, testable modular utilities across the application

Abstract implementation details, and simply provide a convenient API to other parts of the application.

Provide persistent application state across controller, view & directive *instances*

Friday, November 15, 13

Page 54: Angular from Scratch

Services in Detail‘Back-office’ functions, like networking, event-dispatch, etc.

Lazy-loaded singleton modules that persist through the life-cycle of the app, once instantiated.

Injected dependencies that can be used by any other module

Examples: $http, $log, $location, $route, & services used only by Angular: $provide, $injector, $parse

Friday, November 15, 13

Page 55: Angular from Scratch

Services: A MetaphorIn some ways, an Angular Service is little more than a stateful, application-wide controller.

Friday, November 15, 13

Page 56: Angular from Scratch

How are custom Services different from built-ins?

They’re not.

At all.

No, really.

(Well, OK: they’re different in naming conventions: don’t use ‘$’ in your custom services.)

Friday, November 15, 13

Page 57: Angular from Scratch

Defining ServicesThere are wayyy too many patterns for defining a service, and the Angular docs fail to even mention the simplest, most intuitive one, using the module’s .service() convenience method (which also aliases to .factory):

var app = angular.module('appModule', ['dependency1']);app.service(‘serviceName’, function() { return shinyNewServiceInstance; });

Friday, November 15, 13

Page 58: Angular from Scratch

Defining ServicesThe older version of service creation, which you’ll still find in the docs, involves the module’s config function and calling .factory (or .service) on $provide:

angular.module('appModule',[‘dependency1’]).config(function($provide) { $provide.factory('serviceName', function() { return shinyNewServiceInstance; });});

Friday, November 15, 13

Page 59: Angular from Scratch

So, how crazy complicated is the service instance

itself?

Friday, November 15, 13

Page 60: Angular from Scratch

shinyNewServiceInstanceRelax! Here, we get to rely on standard JS pragmatics:

return either a single function or a revealed module, as you wish

allows public & private properties in the constructor

Friday, November 15, 13

Page 61: Angular from Scratch

Single-Function Serviceangular.module('appModule', [], function($provide) { $provide.factory('notifySvc', function() { var msgs = []; //private variable return function(msg) { //public function msgs.push(msg); if (msgs.length == 3) { alert(msgs.join("\n")); msgs = []; } };});

Just call with notifySvc(msg), after injecting into a controller or directive

Friday, November 15, 13

Page 62: Angular from Scratch

Multi-Property Serviceangular.module('appModule', []).service('notifySvc', function() {

var msgs = []; //private variable return { submit: function(msg) { msgs.push(msg); }, dump: function() { if (msgs.length == 3) {

win.alert(msgs.join("\n")); msgs = [];

} };}});

Just call with notifySvc.submit(msg) and notifySvc.dump()

Friday, November 15, 13

Page 63: Angular from Scratch

Service InstantiationRemember: Services are ‘lazy-loaded singletons’. That means the service instance won’t actually be created until you specifically need it.

You tell Angular you need it by injecting it into a controller, directive, etc.

Friday, November 15, 13

Page 64: Angular from Scratch

Referencing ServicesIn a directive or controller, you can have direct access to a service and its properties, assuming you have injected it properly.

In HTML (an interpolated expression), you can’t reference until you’ve attached it to local $scope. So, in your controller:

$scope.property = serviceName.serviceProperty;

Friday, November 15, 13

Page 65: Angular from Scratch

DIRECTIVESIn Detail

Friday, November 15, 13

Page 66: Angular from Scratch

What are Directives, Again?

Friday, November 15, 13

Page 67: Angular from Scratch

Friday, November 15, 13

Page 68: Angular from Scratch

What Are They, Really?5(-ish) words: Logic & Behavior For UI

“...a way to teach HTML new tricks.”

Anything in your app that touches DOM

Examples: event-handling, behavior management, template pre-processing & insertion, data-binding, ‘Collection Views’, UI Widgets, conditional display, i18n & localization, etc.

Friday, November 15, 13

Page 69: Angular from Scratch

What Are They, Really?The only other Angular construct that really touches the DOM is:

Angular Expressions (text only).

Filters

The rest of it should be in Directives. (Even the ng-view that executes your routing is simply a model-driven directive...)

Friday, November 15, 13

Page 70: Angular from Scratch

What Are They, Really?Structurally speaking, a Directive is just a function that’s attached to an element.

But not just a function: a whole execution environment. Really, Directives are mini-applications.

You can think of them as little robotic pilots that live on your DOM elements & tell them what to do.

Friday, November 15, 13

Page 71: Angular from Scratch

Friday, November 15, 13

Page 72: Angular from Scratch

What AREN’T they?Directives.

Aren’t.

Just.

Where.

Your.

JQuery.

Goes!

Please,

God:

No.

Friday, November 15, 13

Page 73: Angular from Scratch

I

BUT...Friday, November 15, 13

Page 74: Angular from Scratch

Angular isn’t just another way to

organize the same old UI code!!!

Friday, November 15, 13

Page 75: Angular from Scratch

Opinionated Principles

1.Declarative, Model-Driven Behavior

Friday, November 15, 13

Page 76: Angular from Scratch

Why Declarative?IMPERATIVE = YOUR PROBLEM

DECLARATIVE = SOMEBODY ELSE’S PROBLEM

Easier To Read, Maintain: Why scatter event-listeners across 100 linked JS files, then need to go search for them to find out what’s happening on an element.

Friday, November 15, 13

Page 77: Angular from Scratch

Declarativeness ROCKSYou’re trying to find handlers for this element:

Well, where are the event-handlers? On ‘#1’? On ‘.B’? ‘.C’? On ‘button’? What if it’s on ‘parentDiv>:first-child’?

You can’t misunderstand what’s happening with declarative directives:

<button id=”1” class=”B C”></button>

<button md-action-handler></button>

Friday, November 15, 13

Page 78: Angular from Scratch

Extending HTML...HTML is NOT a virgin bride or hothouse flower.

The Semantics Wars are over. HTML is a highly-abstracted, Object-Oriented language for app interfaces and for *presenting* documents. Docs themselves are increasingly stored in other formats, like markdown.

We’re not abandoning accessibility. But it’s not a binary choice, anyway.

Friday, November 15, 13

Page 79: Angular from Scratch

1.Declarative, Model-Driven Behavior

2.Modularity, Reusability across contexts: Write Once, Run Anywhere

Opinionated Principles

Friday, November 15, 13

Page 80: Angular from Scratch

ReusabilityIt’s all about context-awareness, data-binding & DI.

Directives know their own element and local scope.

You can pass additional data into directives as attributes, right on the element.

Friday, November 15, 13

Page 81: Angular from Scratch

<div id="header_tabs"><a href="#/home" active-tab="1">HOME</a><a href="#/finance" active-tab="1">Finance</a><a href="#/hr" active-tab="1">Human Resources</a><a href="#/quarterly" active-tab="1">Quarterly</a>

</div>

AND...<div id="subnav_tabs"><a href="#/hr/pay" active-tab="2">Pay</a><a href="#/hr/benefits" active-tab="2">Benefits</a><a href="#/hr/help" active-tab="2">Help</a>

</div>

Friday, November 15, 13

Page 82: Angular from Scratch

1.Declarative, Model-Driven Behavior

2.Modularity, Reusability across contexts: Write Once, Run Anywhere

3.Keep it Local

Opinionated Principles

Friday, November 15, 13

Page 83: Angular from Scratch

No...

Friday, November 15, 13

Page 84: Angular from Scratch

Yes: ‘Local’Sticks to a self-contained, modular scope, which understands its context: inside the directive, `element` is like `this`.

Uses messages, models to affect things elsewhere.

Easier to maintain, easier to read, easier to scale.

But the challenge to all that is:

Friday, November 15, 13

Page 85: Angular from Scratch

My Awesome Website

Sweet Product

Product Description: Lorem ipsum dolor sit amet, consectetur adipiscing elit. In erat mauris, faucibus quis pharetra sit amet, pretium ac libero. Etiam vehicula eleifend bibendum. Morbi gravida metus ut sapien condimentum sodales mollis augue sodales. Vestibulum quis quam at sem placerat aliquet. Curabitur a felis at sapien ullamcorper fermentum. Mauris molestie arcu et lectus iaculis sit amet eleifend eros posuere. Fusce nec porta orci.

Integer vitae neque odio, a sollicitudin lorem. Aenean orci mauris, tristique luctus fermentum eu, feugiat vel massa. Fusce sem sem, egestas nec vulputate vel, pretium sit amet mi. Fusce ut nisl id risus facilisis euismod. Curabitur et elementum purus. Duis tincidunt fringilla eleifend. Morbi id lorem eu ante adipiscing feugiat. Sed congue erat in enim eleifend dignissim at in nisl. Donec tortor mauris, mollis vel pretium vitae, lacinia nec sapien. Donec erat neque, ullamcorper tincidunt iaculis sit amet, pharetra bibendum ipsum. Nunc mattis risus ac ante consequat nec pulvinar neque molestie. Etiam interdum nunc at metus lacinia non varius erat dignissim. Integer elementum, felis id facilisis vulputate, ipsum tellus venenatis dui, at blandit nibh massa in dolor. Cras a ultricies sapien. Vivamus adipiscing feugiat pharetra.

$899.99 Buy Now!

Cart: 1 Item(s)

Clicking Here

Needs to Change

Things Here

Friday, November 15, 13

Page 86: Angular from Scratch

Let’s Build Some!but first...Questions?

Friday, November 15, 13

Page 87: Angular from Scratch

Directive NamesAngular uses a convention borrowed from other JS projects: names in HTML are hyphenated...

while identifiers in the JS are camel-cased:

Expect Angular to do this conversion automatically. Don’t fight it.

.directive(‘sampleDirective’, function(){})

<sample-directive></sample-directive>

Friday, November 15, 13

Page 88: Angular from Scratch

How are custom directives different from built-in?

They’re not.

At all.

No, really.

(Well, OK: they’re different in naming conventions: don’t use ‘ng-’ in your custom directives.)

Friday, November 15, 13

Page 89: Angular from Scratch

CREATION.directive() is a method we call on an angular.module(), either at creation time or via reference, passing a name and a factory function

The factory will return either a function or an object containing a function and other settings

angular .module('moduleName', ['dependency1', 'dependency2']) .directive('directiveName', factoryFunction() {})

Friday, November 15, 13

Page 90: Angular from Scratch

Factories(Note, when we talk about generic ‘factories’, we don’t mean $factory, which is an Angular implementation service.)

The factory pattern is all about Functional Programming: using basic Javascript functions to build and return either naiive objects or other functions.

Friday, November 15, 13

Page 91: Angular from Scratch

What do We Do With The Factory Function?

Friday, November 15, 13

Page 92: Angular from Scratch

Two Basic Options:Return a

Config Object or a ‘Linking Function’

Friday, November 15, 13

Page 93: Angular from Scratch

Friday, November 15, 13

Page 94: Angular from Scratch

Friday, November 15, 13

Page 95: Angular from Scratch

You’ll See Later, But Ignore For Today:

Returning only the Link function

Link vs. Compile

Pre-Link vs. Post-Link

Friday, November 15, 13

Page 96: Angular from Scratch

Friday, November 15, 13

Page 97: Angular from Scratch

Using a Config Objectangular.module('moduleName').directive('sampleDirective', function(){ return { link: function(scope, element, attrs) { // this example binds a behavior to the // mouseenter event element.bind("mouseenter", function(){ ... do stuff after mouseenter ... } },

restrict: ‘E’, template: “<div>Hello, World!</div>” }})

Everything but `link` is optional.

Friday, November 15, 13

Page 98: Angular from Scratch

Link Function Args.directive('sampleDirective', function(){ return { link: function(scope, element, attrs) { // this example binds a behavior to the // mouseenter event element.bind("mouseenter", function(){ ... do stuff after mouseenter ... } },

restrict: ‘E’, template: <div>Hello, World!</div> }})

Friday, November 15, 13

Page 99: Angular from Scratch

Link Function Args3 standard params for a link function. (Plus optional 4th: controller.) They’re supplied as args by the directive function, if specified.

scope: whatever scope object is local

element: element declared on: `this`

attrs: an object containing the html attributes defined on the element, including the directive invocation itself

Supplied to the function not by name but in order. Call them whatever you want.

Friday, November 15, 13

Page 100: Angular from Scratch

jqLite: your path to the DOM Angular will defer to JQuery, if present, but provides its own subset of JQuery for basic DOM tasks.

You can’t just use $(), nor find using selectors, unfortunately.

But all built-in `element` refs are already pre-wrapped in jqlite object

Chain methods as you normally would

Friday, November 15, 13

Page 101: Angular from Scratch

addClass()• after()• append()• attr()• bind() • children()• clone()• contents()• css()• data()• eq()• find() • hasClass()• html()• next()• on()

• off() • parent()• prepend()• prop()• ready()• remove()• removeAttr()• removeClass()• removeData()• replaceWith()• text()• toggleClass()• triggerHandler() • unbind() • val()• wrap()

Friday, November 15, 13

Page 102: Angular from Scratch

Using jqLite (angular.element).directive('sampleDirective', function(){ return { link: function(scope, element, attrs) { // this example binds a behavior to the // mouseenter event element.bind("mouseenter", function(){ ... do stuff after mouseenter ... } },

restrict: ‘E’, template: <div>Hello, World!</div> }})

$(‘selector’).bind(‘mouseenter’, function() {})

Friday, November 15, 13

Page 103: Angular from Scratch

ACK! THPPPT!!

.bind() is ancient!

Where’s .live() ?!?

.on() ?!?Friday, November 15, 13

Page 104: Angular from Scratch

Friday, November 15, 13

Page 105: Angular from Scratch

A Thought:If angular.element() / jqlite doesn’t support what you’re trying to do... ask yourself: why not?

Because they’re lazy bastards?

Not so much. Think about other options.

Go with the grain, and Angular will reward you.

Friday, November 15, 13

Page 106: Angular from Scratch

Directive TemplatesTemplates can be stored as strings on the `template:` property

They can also be loaded from a file, using: `templateUrl: path/to/file/template.html’

Friday, November 15, 13

Page 107: Angular from Scratch

Templates.directive('sampleDirective', function(){ return { link: function(scope, element, attrs) { // this example binds a behavior to the // mouseenter event element.bind("mouseenter", function(){ ... do stuff after mouseenter ... } },

restrict: ‘E’, template: ‘<div>Hello, World!</div>’//or:

templateUrl: ‘path/to/file.html’})

Friday, November 15, 13

Page 108: Angular from Scratch

The Restrict Property.directive('sampleDirective', function(){ return { link: function(scope, element, attrs) { // this example binds a behavior to the // mouseenter event element.bind("mouseenter", function(){ ... do stuff after mouseenter ... } },

restrict: ‘E’, template: <div>Hello, World!</div> }})

Friday, November 15, 13

Page 109: Angular from Scratch

The Restrict PropertyRemember that directives are re-usableSo, we can restrict the usage of a directive to (a) specific context(s), so that we don’t accidentally try to use it in a situation it wasn’t designed for:

‘E’ = Element‘A’ = Attribute‘C’ = Class‘M’ = Comment

Stack as a single string: ‘EACM’. Defaults to ‘A’.

Friday, November 15, 13

Page 110: Angular from Scratch

The Replace PropertyBy default, a directive element will wrap the contents of a template. The `element` object will be the outer directive element.

To instead replace the directive element (and object) with the contents of the template, use {replace: true}

This is esp critical when declaring as an element...

Friday, November 15, 13

Page 111: Angular from Scratch

DirectivesDEMO BREAKDOWN 1:

Enter-Leave

Friday, November 15, 13

Page 112: Angular from Scratch

So, about that:Model-Driven & LocalDirective Design...

Friday, November 15, 13

Page 113: Angular from Scratch

Specifically, theModel-Driven

part...

Friday, November 15, 13

Page 114: Angular from Scratch

Why Model-Driven?

After all, the imperative approach works fine...

...if you’re omniscient and precognitive.

... and you really, really like refactoring.

Friday, November 15, 13

Page 115: Angular from Scratch

How Can Directives React to Models?

With $watch!

Friday, November 15, 13

Page 116: Angular from Scratch

DirectivesDEMO BREAKDOWN 2:

CLOCK

(haha! Get it? We’re going to usea clock to demo $watch...)

Friday, November 15, 13

Page 117: Angular from Scratch

Keeping Directive Design Local

Friday, November 15, 13

Page 118: Angular from Scratch

How Can Directives React to Stuff that

Happens Far, Far Away?Again, with models & $watch!

But sometimes, the inheritance chain isn’t a good solution. For those times...

Angular events! $on(), $emit(), $broadcast()

Friday, November 15, 13

Page 119: Angular from Scratch

Advanced Topic:Inter-Scope Communication

Use $watch to monitor properties of local $scope or one it inherits from

That works great when you only need data to flow in one direction (up) and only on one branch of the tree.

What about when you need to go downwards, or sideways?

Or a whole bunch of places at once?

Friday, November 15, 13

Page 120: Angular from Scratch

$rootScope

Main/Nav Controller

$scope

View 1 Controller

$scope

View 2 Controller

$scope

Directive A-1$scope

Directive B$scope

Directive A-2$scope

Directive C$scope

???

??????

???

???

Friday, November 15, 13

Page 121: Angular from Scratch

Angular Events to The Rescue!!!

Just like how a ‘click’ event bubbles up through the DOM tree, you can $emit() an Angular event up the $scope tree, from any starting point.

Better than the DOM, you can also $broadcast() an event down the $scope tree.

$broadcast()-ing from $rootScope gets you the whole shebang.

Friday, November 15, 13

Page 122: Angular from Scratch

Friday, November 15, 13

Page 123: Angular from Scratch

Angular Events to The Rescue!!!

With events, there’s no need to laboriously climb your way up the $scope tree. You also eliminate the chance of getting the wrong scope.

You also get full de-coupling of a controller/directive from a particular place in your app. Use it anywhere, $broadcast() everywhere.

Friday, November 15, 13

Page 124: Angular from Scratch

Angular Events to The Rescue!!!

And you don’t even need to predict who all the recipients will be. By sending: $rootScope.$broadcast(‘gameOver’)your whole app gets the information,

You can consume the event as many places as you like, with:$scope.$on(‘gameOver’, handlerFunc)

Friday, November 15, 13

Page 125: Angular from Scratch

DirectivesDEMO BREAKDOWN 3:

ActiveTab

Friday, November 15, 13

Page 126: Angular from Scratch

CODA

Friday, November 15, 13

Page 130: Angular from Scratch

Angular 1.2 New Features

The new animations, in particular, are super-righteous: declare standard CSS animations in classes, then Angular will apply them while migrating content in and out of the DOM.

Friday, November 15, 13

Page 131: Angular from Scratch

Thank You!

about.me/XML

Friday, November 15, 13