intro to angular.js directives

64
Angular Directives @ NationJS, 2013 by: Christian Lilley about.me/xml @xmlilley Friday, October 4, 13

Upload: christian-lilley

Post on 10-May-2015

3.617 views

Category:

Technology


0 download

DESCRIPTION

Delivered at NationJS Conference, In Silver Spring MD, on 10/4/13.

TRANSCRIPT

Page 1: Intro to Angular.JS Directives

Angular Directives

@ NationJS, 2013

by: Christian Lilleyabout.me/xml @xmlilley

Friday, October 4, 13

Page 2: Intro to Angular.JS Directives

What are Directives?

Friday, October 4, 13

Page 3: Intro to Angular.JS Directives

Friday, October 4, 13

Page 4: Intro to Angular.JS Directives

Angular, Ember, BackBone: Google Trends

Friday, October 4, 13

Page 5: Intro to Angular.JS Directives

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, October 4, 13

Page 6: Intro to Angular.JS Directives

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, October 4, 13

Page 7: Intro to Angular.JS Directives

What AREN’T they?Directives.

Are.

Not.

Where.

Your.

JQuery.

Goes!

Please,

God:

No.

Friday, October 4, 13

Page 8: Intro to Angular.JS Directives

I

BUT...Friday, October 4, 13

Page 9: Intro to Angular.JS Directives

I

Moar

“The Superheroic

MVW framework.”

Friday, October 4, 13

Page 10: Intro to Angular.JS Directives

And Angular isn’t just another way to organize the same old UI code!!!

Friday, October 4, 13

Page 11: Intro to Angular.JS Directives

Opinionated Principles

1.Declarative, Model-Driven Behavior

Friday, October 4, 13

Page 12: Intro to Angular.JS Directives

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, October 4, 13

Page 13: Intro to Angular.JS Directives

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, October 4, 13

Page 14: Intro to Angular.JS Directives

Why NOT Declarative?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 religion.

Friday, October 4, 13

Page 15: Intro to Angular.JS Directives

1.Declarative, Model-Driven Behavior

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

Opinionated Principles

Friday, October 4, 13

Page 16: Intro to Angular.JS Directives

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, October 4, 13

Page 17: Intro to Angular.JS Directives

<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, October 4, 13

Page 18: Intro to Angular.JS Directives

1.Declarative, Model-Driven Behavior

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

3.Keep it Local

Opinionated Principles

Friday, October 4, 13

Page 19: Intro to Angular.JS Directives

No...

Friday, October 4, 13

Page 20: Intro to Angular.JS Directives

Yes: ‘Local’Sticks to a self-contained, modular scope, which understands its context.

Uses messages, models to affect things elsewhere.

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

But the challenge is this:

Friday, October 4, 13

Page 21: Intro to Angular.JS Directives

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, October 4, 13

Page 22: Intro to Angular.JS Directives

Let’s Build Some!

Friday, October 4, 13

Page 23: Intro to Angular.JS Directives

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, October 4, 13

Page 24: Intro to Angular.JS Directives

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, October 4, 13

Page 25: Intro to Angular.JS Directives

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, October 4, 13

Page 26: Intro to Angular.JS Directives

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, October 4, 13

Page 27: Intro to Angular.JS Directives

What do We Do With The Factory Function?

Friday, October 4, 13

Page 28: Intro to Angular.JS Directives

Two Basic Options:Return a

Config Object or a ‘Linking Function’

Friday, October 4, 13

Page 29: Intro to Angular.JS Directives

Friday, October 4, 13

Page 30: Intro to Angular.JS Directives

Friday, October 4, 13

Page 31: Intro to Angular.JS Directives

You’ll See Later, But Ignore For Today:

Returning only the Link function

Link vs. Compile

Pre-Link vs. Post-Link

Friday, October 4, 13

Page 32: Intro to Angular.JS Directives

Friday, October 4, 13

Page 33: Intro to Angular.JS Directives

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, October 4, 13

Page 34: Intro to Angular.JS Directives

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, October 4, 13

Page 35: Intro to Angular.JS Directives

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, October 4, 13

Page 36: Intro to Angular.JS Directives

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, October 4, 13

Page 37: Intro to Angular.JS Directives

• 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, October 4, 13

Page 38: Intro to Angular.JS Directives

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, October 4, 13

Page 39: Intro to Angular.JS Directives

ACK! THPPPT!!

.bind() is ancient!

Where’s .live() ?!?

.on() ?!?Friday, October 4, 13

Page 40: Intro to Angular.JS Directives

Friday, October 4, 13

Page 41: Intro to Angular.JS Directives

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, October 4, 13

Page 42: Intro to Angular.JS Directives

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, October 4, 13

Page 43: Intro to Angular.JS Directives

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, October 4, 13

Page 44: Intro to Angular.JS Directives

DEMO BREAKDOWN 1

Friday, October 4, 13

Page 45: Intro to Angular.JS Directives

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, October 4, 13

Page 46: Intro to Angular.JS Directives

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, October 4, 13

Page 47: Intro to Angular.JS Directives

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, October 4, 13

Page 48: Intro to Angular.JS Directives

DEMO BREAKDOWN 2

Friday, October 4, 13

Page 49: Intro to Angular.JS Directives

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

Friday, October 4, 13

Page 50: Intro to Angular.JS Directives

Specifically, theModel-Driven

part...

Friday, October 4, 13

Page 51: Intro to Angular.JS Directives

Why Model-Driven?

After all, the imperative approach works fine...

...if you’re omniscient and precognitive.

... and you really, really like refactoring.

Friday, October 4, 13

Page 52: Intro to Angular.JS Directives

How Can Directives React to Models?

With $watch!

Friday, October 4, 13

Page 53: Intro to Angular.JS Directives

DEMO BREAKDOWN 3:CLOCK

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

Friday, October 4, 13

Page 54: Intro to Angular.JS Directives

Keeping Directive Design Local

Friday, October 4, 13

Page 55: Intro to Angular.JS Directives

How Can Directives React to Stuff that

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

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

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

Friday, October 4, 13

Page 56: Intro to Angular.JS Directives

DEMO BREAKDOWN 4:ActiveTab

Friday, October 4, 13

Page 57: Intro to Angular.JS Directives

Often Overlooked:Controllers

Directive Config Objects can provide an optional controller.

At first, you think: why?

One option: alternative to routing

Routes have controllers

Sometimes, you don’t want routes

Friday, October 4, 13

Page 58: Intro to Angular.JS Directives

Often Overlooked:Controllers

With its own controller, a directive is a full, standalone interface component, with its own data context, which can be built or torn-down on demand.

Friday, October 4, 13

Page 59: Intro to Angular.JS Directives

Isolate ScopeWe have the option, in directives, of using either:

the local $scope (from our controller, possibly)a new, per-instance, ‘isolate scope’

Isolate scopes still have a parent $scope, but they’re *encapsulated*: or, detached from the inheritance chain.This is especially useful with repeats, so variables can be fully local to the instance

Friday, October 4, 13

Page 60: Intro to Angular.JS Directives

Creating Isolate ScopeCreating isolate scope is as simple as an object literal assigned to the `scope:` property on the config object:

.directive('sampleDirective', function(){ return { link: function(scope, element, attrs) { element.bind("mouseenter", function(){ ... do stuff after mouseenter ... } },

restrict: ‘E’, scope: {name: “Bob”,

hobby: “@”}}})

Friday, October 4, 13

Page 61: Intro to Angular.JS Directives

Cool! But what’s that ‘@’ doing there?

Friday, October 4, 13

Page 62: Intro to Angular.JS Directives

Isolate Scope Data-BindingAngular provides us with ways to bind the value of properties in isolate scope to attributes on the element, using special operators:

.directive('sampleDirective', function(){ return { link: function() {}, restrict: ‘E’, scope: {name: “Bob”,

hobby: “@”} //alt. form:{pasttime: ‘@hobby’}

}})

<sample-directive hobby=”scuba-diving”>

Friday, October 4, 13

Page 63: Intro to Angular.JS Directives

Data-Binding OperatorsBy default, an operator alone will be assumed to refer to a same-named attrAlternately, use form ‘@hobby’ to specifyOptions:

‘@’- binds the local scope property to primitive value of the DOM attribute. Result is always a string. (Attributes are strings.)‘=’- binds the local scope property to a parent scope property having same name as the value of the DOM attribute.‘&’- binds the local scope property to the output of an expression defined in the DOM attribute. It’s like a function-wrapper.

Friday, October 4, 13

Page 64: Intro to Angular.JS Directives

Thank You!

about.me/xml

Friday, October 4, 13