• No results found

angular js level 01-05

N/A
N/A
Protected

Academic year: 2021

Share "angular js level 01-05"

Copied!
164
0
0

Loading.... (view fulltext now)

Full text

(1)
(2)

Shaping Up with Angular

Level 1: Getting Started

(3)

What you need to know

Must know

Not so important

Nice to know

Automated Testing

BDD - Behavior Driven Development TDD - Test Driven Development

etc

HTML & CSS

JavaScript jQuery Ruby on Rails

Python, PHP, etc Databases

(4)

Why Angular?

If you’re using JavaScript to create a dynamic website,

Angular is a good choice.

• Angular helps you organize your JavaScript

• Angular helps create responsive (as in fast) websites.

• Angular plays well with jQuery

(5)

Traditional Page-Refresh

Screencast: Request-Response Application

NOTE: Time between user 


(6)

Web Server

HTML JavaScript

Response with Webpage & Assets

Web Browser

URL Request to server

Response with Webpage & Assets

User clicks on link, new Request

HTML JavaScript

Browser loads up

entire webpage.

Browser loads up

(7)

Screencast: Request-Response Application

NOTE: Note how responsive the page is

A “responsive” website using Angular

(8)

Web Server

Response with Webpage

& Assets

Web Browser

URL Request to

server

Response with JSON

Data

User clicks on link,

new Request

HTML JavaScript

DATA

Browser loads up

entire webpage.

Data is loaded into

existing page.

(9)

Modern API-Driven Application

HTML

Browser

App

Data Source

Mobile

App

Developers

Server

API

(10)

A client-side JavaScript Framework for adding interactivity to HTML.

app.js index.html

How do we tell our HTML when to trigger our JavaScript?

<!DOCTYPE html>
 <html>
 <body
 . . . </body>
 </html> function Store


alert('Welcome, Gregg!');
 }


(){

>

(11)

<!DOCTYPE html>
 <html>
 <body
 . . . </body>
 </html> app.js function Store


alert('Welcome, Gregg!');
 }


A Directive is a marker on a HTML tag that tells Angular to run or reference

some JavaScript code.

Directives

Name of

function to call

index.html Controller(){ ng-controller="StoreController">

(12)

The Flatlanders Store!

Screencast: Flatlanders Store

Fully Functional

(13)

Download AngularJS

http

://angularjs.org/

We’ll need angular.min.js

Downloading the libraries

Download Twitter Bootstrap

http://getbootstrap.com/

(14)

<!DOCTYPE html>

<html>

<head>

<

link

rel

=

"stylesheet"

type

=

"text/css"

href

=

"bootstrap.min.css"

/>

</head>

<body>

<

script

type

=

"text/javascript"

src

=

"angular.min.js"

></

script

>


</body>

</html>

Getting Started

index.html

Twitter Bootstrap

AngularJS

(15)

Modules

• Where we write pieces of our Angular application.

• Makes our code more maintainable, testable, and readable.

• Where we define dependencies for our app.

(16)

Creating Our First Module

Dependencies

Other libraries we might need. 
 We have none... for now…

Application

Name

AngularJS

(17)

Including Our Module

var

app

=

angular.module(

'store'

, [

]);

app.js

index.html

<!DOCTYPE html>

<html>

<head>

<

link

rel

=

"stylesheet"

type

=

"text/css"

href

=

"bootstrap.min.css"

/>

</head>

<body>

<

script

type

=

"text/javascript"

src

=

"angular.min.js"

></

script

>

<

script

type

=

"text/javascript"

src

=

"app.js"

></

script

>

</body>

(18)

Including Our Module

var

app

=

angular.module(

'store'

, [

]);

app.js

<!DOCTYPE html>

<html

ng-app=

"store"

>

<head>

<

link

rel

=

"stylesheet"

type

=

"text/css"

href

=

"bootstrap.min.css"

/>

</head>

<body>

<

script

type

=

"text/javascript"

src

=

"angular.min.js"

></

script

>


<

script

type

=

"text/javascript"

src

=

"app.js"

></

script

>


</body>

</html>

Run this module

when the document

loads.

(19)

Allow you to insert dynamic values into your HTML.

Expressions

Numerical Operations

evaluates to

String Operations

evaluates to

+ More Operations:

http://docs.angularjs.org/guide/expression

<p>

I am {{4 + 6}}


</p>

<p>

{{"hello" + " you"}}


</p>

<p>

I am 10


</p>

<p>

hello you


</p>

(20)

Including Our Module

var

app

=

angular.module(

'store'

, [

]);

app.js

<!DOCTYPE html>

<html

ng-app=

"store"

>

<head>

<

link

rel

=

"stylesheet"

type

=

"text/css"

href

=

"bootstrap.min.css"

/>

</head>

<body>

<

script

type

=

"text/javascript"

src

=

"angular.min.js"

></

script

>


<

script

type

=

"text/javascript"

src

=

"app.js"

></

script

>


<p>

{{"hello" + " you"}}

</p>

</body>

(21)
(22)

Working With Data

...just a simple

object we want to

print to the page.

var

gem

=

{


name

:

'Dodecahedron'

,


price

:

2.95

,


description

:

'. . .'

,


}

.

(23)

Controllers

app.js

Notice that controller is attached to (inside) our app.

Controllers are where we define our app’s behavior by defining

functions and values.

Wrapping your Javascript

in a closure is a good habit!

var

gem

=

{


name

:

'Dodecahedron'

,


price

:

2.95

,


description

:

'. . .'

,


}

.

})();

(

function

(){


var

app

=

angular.module(

'store'

, [

]);

app.controller(

'StoreController'

,

function

(){


(24)

Storing Data Inside the Controller

app.js

Now how do we

print out this

data inside our

webpage?

this.product

=

gem;

var

gem

=

{


name

:

'Dodecahedron'

,


price

:

2.95

,


description

:

'. . .'

,


}

.

})();

(

function

(){


var

app

=

angular.module(

'store'

, [

]);

app.controller(

'StoreController'

,

function

(){


(25)

<!DOCTYPE html>

<html

ng-app=

"store"

>

<head>

<

link

rel

=

"stylesheet"

type

=

"text/css"

href

=

"bootstrap.min.css"

/>

</head>

!

!

!

!

!

!

!

!

</html>

<body>

<div>

<h1>

Product Name

</h1>

<h2> $

Product Price

</h2>

<p>

Product Description

</p>

</div>

<

script

type

=

"text/javascript"

src

=

"angular.min.js"

></

script

>


<

script

type

=

"text/javascript"

src

=

"app.js"

></

script

>


</body>

Our Current HTML

Let’s load our data into

this part of the page.

}

(26)

<body>
 <div>
 <h1> Product Name </h1>
 <h2> $Product Price </h2>
 <p> Product Description </p>
 </div>


<script type="text/javascript" src="angular.min.js"></script>
 <script type="text/javascript" src="app.js"></script>


</body>

(function(){


var app = angular.module('store', [ ]);


app.controller('StoreController', function(){
 this.product = gem;

}); . . .

})(); app.js

index.html

(27)

<body>


<div ng-controller="StoreController as store">
 <h1> Product Name </h1>


<h2> $Product Price </h2>


<p> Product Description </p>
 </div>


<script type="text/javascript" src="angular.min.js"></script>
 <script type="text/javascript" src="app.js"></script>


</body>

Attaching the Controller

(function(){


var app = angular.module('store', [ ]);


app.controller('StoreController', function(){
 this.product = gem;

}); . . .

})(); app.js

index.html

Controller name

Alias

Directive

(28)

<body>


<div ng-controller="StoreController as store">


!

!

</div>


<script type="text/javascript" src="angular.min.js"></script>
 <script type="text/javascript" src="app.js"></script>


</body> index.html

Displaying Our First Product

(function(){


var app = angular.module('store', [ ]);


app.controller('StoreController', function(){
 this.product = gem;

}); . . . })(); app.js <h1> {{store.product.name}} </h1>
 <h2> ${{store.product.price}} </h2>
 <p> {{store.product.description}} </p>

(29)

Understanding Scope

Would never print a

value!

The scope of

the Controller

is only inside

here...

}

{{store.product.name}} <h1> {{store.product.name}} </h1>
 <h2> ${{store.product.price}} </h2>
 <p> {{store.product.description}} </p> <body>


<div ng-controller="StoreController as store">


!

!

</div>


<script type="text/javascript" src="angular.min.js"></script>
 <script type="text/javascript" src="app.js"></script>


(30)
(31)

</div>


<script type="text/javascript" src="angular.min.js"></script>
 <script type="text/javascript" src="app.js"></script>


</body>

<body ng-controller="StoreController as store">
 <div>
 <h1> {{store.product.name}} </h1>
 <h2> ${{store.product.price}} </h2>
 <p> {{store.product.description}} </p>

Adding A Button

index.html

var

gem

=

{


name

:

'Dodecahedron'

,


price

:

2.95

,


description

:

'. . .'

,

}

.

(32)

var

gem

=

{


name

:

'Dodecahedron'

,


price

:

2.95

,


description

:

'. . .'

,

}

.

canPurchase

:

false

</div>


<script type="text/javascript" src="angular.min.js"></script>
 <script type="text/javascript" src="app.js"></script>


</body>

Adding A Button

index.html

<button

How can we

only show

this button...

...when this is true?

Directives t

o

the rescue!

<body ng-controller="StoreController as store">
 <div>


<h1> {{store.product.name}} </h1>
 <h2> ${{store.product.price}} </h2>


<p> {{store.product.description}} </p>

(33)

var

gem

=

{


name

:

'Dodecahedron'

,


price

:

2.95

,


description

:

'. . .'

,

}

.

canPurchase

:

false

</div>


<script type="text/javascript" src="angular.min.js"></script>
 <script type="text/javascript" src="app.js"></script>


</body>

NgShow Directive

index.html

<button

<body ng-controller="StoreController as store">
 <div>


<h1> {{store.product.name}} </h1>
 <h2> ${{store.product.price}} </h2>


<p> {{store.product.description}} </p>

ng-show="store.product.canPurchase"> Add to Cart </button>

Will only show the element if the

value of the Expression is

(34)
(35)

</div>


<script type="text/javascript" src="angular.min.js"></script>
 <script type="text/javascript" src="app.js"></script>


</body> index.html

<button

<body ng-controller="StoreController as store">
 <div


<h1> {{store.product.name}} </h1>
 <h2> ${{store.product.price}} </h2>


<p> {{store.product.description}} </p>

ng-show="store.product.canPurchase"> Add to Cart </button>

NgHide Directive

If the product is sold out

we want to hide it.

var

gem

=

{


name

:

'Dodecahedron'

,


price

:

2.95

,


description

:

'. . .'

,

}

.

canPurchase

:

true

,

soldOut

:

true

>

(36)

</div>


<script type="text/javascript" src="angular.min.js"></script>
 <script type="text/javascript" src="app.js"></script>


</body> index.html

<button

<body ng-controller="StoreController as store">
 <div


<h1> {{store.product.name}} </h1>
 <h2> ${{store.product.price}} </h2>


<p> {{store.product.description}} </p>

ng-show="store.product.canPurchase"> Add to Cart </button>

NgHide Directive

If the product is sold out

we want to hide it.

This is awkward and

a good example to

use ng-hide!

var

gem

=

{


name

:

'Dodecahedron'

,


price

:

2.95

,


description

:

'. . .'

,

}

.

canPurchase

:

true

,

soldOut

:

true

,

ng-show="!store.product.soldOut">

(37)

</div>


<script type="text/javascript" src="angular.min.js"></script>
 <script type="text/javascript" src="app.js"></script>


</body> index.html

<button

<body ng-controller="StoreController as store">
 <div


<h1> {{store.product.name}} </h1>
 <h2> ${{store.product.price}} </h2>


<p> {{store.product.description}} </p>

ng-show="store.product.canPurchase"> Add to Cart </button>

NgHide Directive

If the product is sold out

we want to hide it.

Much better!

var

gem

=

{


name

:

'Dodecahedron'

,


price

:

2.95

,


description

:

'. . .'

,

}

.

canPurchase

:

true

,

soldOut

:

true

,

ng-hide="store.product.soldOut">

(38)

Multiple Products

app.js var gem = 
 name: "Dodecahedron",
 price: 2.95,
 description: ". . .",
 canPurchase: true,
 },
 {

app.controller('StoreController', function(){
 this.product = gem


(39)

Multiple Products

app.js var gems = [
 
 name: "Dodecahedron",
 price: 2.95,
 description: ". . .",
 canPurchase: true,
 },
 {


name: "Pentagonal Gem",
 price: 5.95,


description: ". . .",
 canPurchase: false,
 }…


];

{

Now we have an array...

How might we display all these

products in our template?

Maybe a

Directive?

app.controller('StoreController', function(){
 this.products = gems


(40)

Working with An Array

index.html

<body ng-controller="StoreController as store">
 <div>


<h1> {{store.products[0].name}} </h1>
 <h2> ${{store.products[0].price}} </h2>


<p> {{store.products[0].description}} </p>


<button ng-show="store.products[0].canPurchase">
 Add to Cart</button>


</div>
 . . .


(41)

index.html

Working with An Array

. . .


</body>

Displaying the first product

is easy enough...

<body ng-controller="StoreController as store">
 <div>


<h1> {{store.products[0].name}} </h1>
 <h2> ${{store.products[0].price}} </h2>


<p> {{store.products[0].description}} </p>
 <button ng-show="


Add to Cart</button>
 </div>

(42)

Working with An Array

index.html

<body ng-controller="StoreController as store">
 <div


<h1> {{store.products[0].name}} </h1>
 <h2> ${{store.products[0].price}} </h2>


<p> {{store.products[0].description}} </p>
 <button ng-show="


Add to Cart</button>
 </div> . . .
 </body> <div>
 <h1> {{store.products[1].name}} </h1>
 <h2> ${{store.products[1].price}} </h2>
 <p> {{store.products[1].description}} </p>


<button ng-show="store.products[1].canPurchase">
 Add to Cart</button>


</div>

Why repeat yourself?

Why repeat yourself?

Why... You get it.

>

store.products[0].canPurchase">

(43)

Working with An Array

index.html

<body ng-controller="StoreController as store">
 <div


<h1> {{product.name}} </h1>
 <h2> ${{product.price}} </h2>


<p> {{product.description}} </p>
 <button ng-show="


Add to Cart</button>
 </div>

. . .


</body>

ng-repeat="product in store.products" product >

Repeat this

section for

each product.

}

.canPurchase">

(44)

What We Have Learned So Far

Directives – HTML annotations that trigger Javascript behaviors

Modules – Where our application components live

Controllers – Where we add application behavior

(45)
(46)
(47)
(48)

Shaping Up with Angular.JS

Level 2: Filters, Directives, and Cleaner Code

(49)

ng-app – attach the Application Module to the page

Directives We Know & Love

ng-controller – attach a Controller function to the page

ng-show / ng-hide – display a section based on an Expression

ng-repeat – repeat a section for each item in an Array

<html

ng-app=

"store"

>

<body ng-controller=

"StoreController as store"

>

<h1

ng-show=

"name"

>

Hello, {{name}}!

</h1>

(50)

Our Current Code

<body

ng-controller=

"StoreController as store"

>

<ul

class=

"list-group"

>

<

li

class

=

"list-group-item"

ng-repeat

=

"product in store.products"

>

<h3>

{{product.name}}

index.html

<

em

class

=

"pull-right"

>

$

{{product.price

}}

</

em

>

</h3>

</

li

>

</ul>

</body>

There’s a better way

to print out prices.

(51)

Our First Filter

Pipe - “send the output into”

Format this into currency

Notice it gives the dollar sign (localized)

Specifies number of decimals

index.html

<

em

class

=

"pull-right"

>

{{product.price | currency

}}

</

em

>

<body

ng-controller=

"StoreController as store"

>

<ul

class=

"list-group"

>

<

li

class

=

"list-group-item"

ng-repeat

=

"product in store.products"

>


<h3>

{{product.name}}

</h3>

</

li

>

</ul>

</body>

$2.00

(52)

{{ data | filter:options }}

Formatting with Filters

*Our Recipe

{{'1388123412323' | date:'MM/dd/yyyy @ h:mma'}}

date

12/27/2013 @ 12:50AM

{{'octagon gem' | uppercase}}

uppercase & lowercase

OCTAGON GEM

{{'My Description' | limitTo:8}}

limitTo

My Descr

<

li ng-repeat

=

"product in store.products | orderBy:'-price'"

>

orderBy

Will list products by descending price.

Without the

-

products would list in ascending order.

<

li ng-repeat

=

"product in store.products | limitTo:3"

>

(53)

var

gems

=

[


{

name

:

'Dodecahedron Gem'

,

price

:

2.95

,


description

:

'. . .'

,


images

: [


{

full

:

'dodecahedron-01-full.jpg'

,

thumb

:

'dodecahedron-01-thumb.jpg'


},


{

full

:

"dodecahedron-02-full.jpg"

,

. . .

Adding an Image Array to our Product Array

Our New Array

Image Object

To display the first image in a product:

{{product.images[0].full}}

(54)

<body

ng-controller=

"StoreController as store"

>

<ul

class=

"list-group"

>

<

li

class

=

"list-group-item"

ng-repeat

=

"product in store.products"

>

<h3>

{{product.name}}

<

em

class

=

"pull-right"

>

{{product.price | currency}}

</

em

>

<

img

ng-src

=

"{{product.images[0].full}}"

/>

</h3>

</

li

>

</ul>

</body>

index.html

Using ng-src for Images

NG-SOURCE

to the rescue!

…the browser tries to load the image

before the Expression evaluates.

Using Angular Expressions inside a

src

attribute causes an error!

(55)
(56)
(57)

More With Directives

How can I make my application

more interactive?

(58)

A Simple Set of Tabs

index.html

<section>

<ul

class=

"nav nav-pills”

>

<

li

> <

a

href

<

li

> <

a

href

<

li

> <

a

href

>Description</

a

> </

li

>

>Specifications</

a

>

</

li

>

>Reviews</

a

>

</

li

>

</ul>

</section>

(59)

Introducing a new Directive!

index.html

Assigning a value to

tab

.

For now just print this value to the screen.

<section>

<ul

class=

"nav nav-pills”

>

<

li

> <

a

href

<

li

> <

a

href

<

li

> <

a

href

>Description</

a

> </

li

>

>Specifications</

a

>

</

li

>

>Reviews</

a

>

</

li

>

{{tab}}

ng-click

=

"tab = 1"

ng-click

=

"tab = 2"

ng-click

=

"tab = 3"

</ul>

</section>

(60)
(61)

When ng-click changes the value of tab …

… the {{tab}} expression automatically gets updated!

!

Expressions define a 2-way Data Binding ...

this means Expressions are re-evaluated when a property changes.

(62)

<div class=

"panel"

<div class=

"panel"

Let’s add the tab content panels

How do we make the tabs trigger the panel to show?

<h4>

Description

</h4>


<p>

{{product.description}}

</p>

</div>

<div class=

"panel"

<h4>

Specifications

</h4>


<blockquote>

None yet

</blockquote>

</div>

<h4>

Reviews

</h4>


<blockquote>

None yet

</blockquote>

</div>

>

>

>

tabs are up here...

(63)

Let’s add the tab content panels

Now when a tab is selected it will show the appropriate panel!

<div class=

"panel"

>

>

>

<h4>

Description

</h4>


<p>

{{product.description}}

</p>

</div>

<h4>

Specifications

</h4>


<blockquote>

None yet

</blockquote>

</div>

<h4>

Reviews

</h4>


<blockquote>

None yet

</blockquote>

</div>

ng-show=

"tab === 1"

ng-show=

"tab === 2"

ng-show=

"tab === 3"

<div class=

"panel"

<div class=

"panel"

show the panel

if tab is the

right number

(64)

But how do we set an

initial value for a tab?

(65)

Setting the Initial Value

index.html

ng-init

allows us to evaluate an expression in the current scope.

<section ng-init=

"tab = 1"

>

<ul

class=

"nav nav-pills"

>

<

li

>

<

a

href

ng-click

=

"tab = 1"

>Description</

a

>

</

li

>

<

li

>

<

a

href

ng-click

=

"tab = 2"

>Specifications</

a

>

</

li

>

<

li

>

<

a

href

ng-click

=

"tab = 3"

>Reviews</

a

>

</

li

>

</ul>

. . .

(66)
(67)

Setting the Active Class

We need to set the class to active if current tab is selected ...

index.html

</ul>

ng-init=

"tab = 1"

>

<ul

class=

"nav nav-pills”

>

>Description</

a

>

>Specifications</

a

>

>Reviews</

a

>

ng-click

=

"tab = 1"

ng-click

=

"tab = 2"

ng-click

=

"tab = 3"

<section

<

li

<

li

<

li

>

>

>

<

a

href

<

a

href

<

a

href

</

li

>

</

li

>

</

li

>

(68)

The ng-class directive

Name of the class to set.

Expression to evaluate

If true, set class to “active”,

otherwise nothing.

index.html

ng-init="tab = 1"> <section

<ul class="nav nav-pills”>

<li <li <li ng-click="tab = 1" ng-click="tab = 2" ng-click="tab = 3" >Description</a> >Specifications</a> >Reviews</a> </li> </li> </li> </ul> . . . > > > ng-class="{ active:tab === 1 }" ng-class="{ active:tab === 2 }" ng-class="{ active:tab === 3 }" <a href <a href <a href

(69)
(70)

Feels dirty, doesn’t it?

All our application’s logic is inside our HTML.

How might we pull this

logic into a Controller?

index.html

<section

<ul class="nav nav-pills">

<li > <a href >Description</a> <li </li> > <a href >Specifications</a> <li </li> > <a href >Reviews</a> </li> </ul> ng-click="tab = 1" " tab = 2 ng-click=" ng-click="tab = 3"

ng-class="{ active:

tab === 1

}">

ng-class="{ active:

tab === 2

}">

ng-class="{ active:tab === 3 }"> <div class="panel" ng-show="

<h4>Description </h4>
 <p>{{product.description}}</p>
 </div> … tab === 1"> ng-init="tab = 1">

(71)

Creating our Panel Controller

index.html

app.js

ng-init="tab = 1"

<section

<ul class="nav nav-pills">

<li > <a href >Description</a> <li </li> > <a href >Specifications</a> <li </li> > <a href >Reviews</a> </li> </ul>

ng-controller="PanelController as panel"

app.controller("PanelController", function(){ }); ng-click="tab = 1" " tab = 2 ng-click=" ng-click="tab = 3"

<li ng-class="{ active:tab === 1 }"> <li ng-class="{ active:tab === 2 }"> <li ng-class="{ active:tab === 3 }"> <div class="panel" ng-show="

<h4>Description </h4>
 <p>{{product.description}}</p>
 </div> … tab === 1"> >

(72)

Moving our tab initializer

index.html

app.js

<section

<ul class="nav nav-pills">

<li > <a href >Description</a> <li </li> > <a href >Specifications</a> <li </li> > <a href >Reviews</a> </li> </ul>

app.controller("PanelController", function(){ });

this.tab = 1; <a href ng-click="tab = 1"

<a href ng-click="tab = 2" <a href ng-click="tab = 3"

<li ng-class="{ active:tab === 1 }"> <li ng-class="{ active:tab === 2 }"> <li ng-class="{ active:tab === 3 }"> <div class="panel" ng-show="

<h4>Description </h4>


<p>{{product.description}}</p>
 </div>

tab === 1">

(73)

Creating our selectTab function

index.html

app.js

<section

<ul class="nav nav-pills">

ng-controller="PanelController as panel">

<li >

<a href ng-click="panel.selectTab(1)">Description</a> <li

</li>

>

<a href ng-click="panel.selectTab(2)">Specifications</a> </li>

<li >

<a href ng-click="panel.selectTab(3) >Reviews</a> </li>

</ul>

"

app.controller("PanelController", function(){

}); this.tab = 1; ng-class="{ active: ng-class="{ active: ng-class="{ active: }"> }"> }"> tab === 1 tab === 2 tab === 3

<div class="panel" ng-show=" <h4>Description </h4>


<p>{{product.description}}</p>
 </div>

tab === 1">

this.tab = setTab; };

function(setTab) { this.selectTab =

(74)

Creating our isSelected function

index.html

app.js

<section

<ul class="nav nav-pills">

ng-controller="PanelController as panel">

<li ng-class="{ active: ng-class="{ active: ng-class="{ active: panel.isSelected(1) panel.isSelected(2) panel.isSelected(3) }"> }"> }">

<a href ng-click="panel.selectTab(1)" >Description</a> <a href ng-click="panel.selectTab(2)">Specifications</a> <a href ng-click="panel.selectTab(3)">Reviews</a>

</li> </ul>

panel.isSelected(1) <div class="panel" ng-show=" ">

<h4>Description </h4>
 <p>{{product.description}}</p>
 </div> … </li> <li </li> <li <li </li>

app.controller("PanelController", function(){

});

this.tab = 1;

this.isSelected = function(checkTab){ return this.tab === checkTab;

};

this.tab = setTab; };

function(setTab) { this.selectTab =

(75)
(76)
(77)
(78)
(79)

Shaping Up with Angular

Level 3: Forms, Models, and Validations

(80)

More Directives: Forms & Models

(81)

Adding reviews to our products

app.js

app.controller("StoreController", function(){


this.products = [
 { 


name: 'Awesome Multi-touch Keyboard', 
 price: 250.00,
 description: "...",
 images: [...],
 reviews: [
 { 
 stars: 5,


body: "I love this product!",
 author: "[email protected]"


},


{ 


stars: 1,


body: "This product sucks",
 author: "[email protected]"


}


(82)

<

li

class

=

"list-group-item"

ng-repeat

=

"product in store.products"

>

. . .

<div

class=

"panel"

ng-show=

"panel.isSelected(3)"

>

<h4>

Reviews

</h4>

<blockquote

ng-repeat=

"review in product.reviews"

>

<

b

>

Stars: {{review.stars}}

</

b

>

{{review.body}}

<

cite

>

by: {{review.author}}

</

cite

>

</blockquote>

</div>

Looping Over Reviews in our Tab

(83)

We’re displaying Reviews!

(84)

<h4>

Reviews

</h4>

<blockquote

ng-repeat=

"review in product.reviews"

>

...

</blockquote>

Writing out our Review Form

index.html

<form

name=

"reviewForm"

>

<

select

<

option

value

=

"1"

>1 star</

option

>

<

option

value

=

"2"

>2 stars</

option

>

. . .


</

select

>

<textarea></textarea>

<

label

>

by:

</

label

>

<

input

type

=

"email"

/>

<

input

type

=

"submit"

value

=

"Submit"

/>

</form>

(85)

With Live Preview

,.

index.html

<blockquote>

<

b

>

Stars: {{review.stars}}

</

b

>

{{review.body}}

<

cite

>

by: {{review.author}}

</

cite

>

</blockquote>

How do we bind this review

object to the form?

<

option

value

=

"1"

>1 star</

option

>

<

option

value

=

"2"

>2 stars</

option

>

. . .

</

select

>

<textarea></textarea>

<

label

>by:</

label

>

<

input type

=

"email"

/>

<

input

type

=

"submit"

value

=

"Submit"

/>

</form>

<

select

>

(86)

Introducing ng-model

&,

index.html

ng-model

=

"review.stars"

ng-model=

"review.body"

ng-model

=

"review.author"

<

select

>

<

option

value

=

"1"

>1 star</

option

>

<

option

value

=

"2"

>2 stars</

option

>

. . .

</

select

>

<textarea

></textarea>

<

label

>by:</

label

>

<

input

type

=

"email"

/>

<

input

type

=

"submit"

value

=

"Submit"

/>

</form>

<form

name=

"reviewForm"

>

<blockquote>

<

b

>Stars: {{review.stars}}</

b

>

{{review.body}} 


<

cite

>by: {{review.author}}</

cite

> 


</blockquote>

ng-model binds the

form element value

to the property

(87)

Live Preview In Action

(88)

<input ng-model="review.terms" type="checkbox" /> I agree to the terms

Two More Binding Examples

With a Checkbox

With Radio Buttons

Sets value to true or false

Sets the proper value based on which is selected

What color would you like?

<

input

ng-model

=

"review.color"

type

=

"radio"

value

=

"red"

/>

Red

<

input

ng-model

=

"review.color"

type

=

"radio"

value

=

"blue"

/>

Blue

(89)
(90)

We need to Initialize the Review

index.html

We could do

ng-init

, but

we’re better off

creating a controller.

<label>by:</label> 


<input ng-model="review.author" type="email" />
 <input type="submit" value="Submit" />


</form>

<form

name="

reviewForm

">

<b>Stars: {{review.stars}}</b> {{review.body}}

<cite>by: {{review.author}}</cite> </blockquote>

<blockquote>

<select ng-model="review.stars">

<option value="1">1 star</option>
 <option value="2">2 stars</option>
 . . .


</select>

(91)

Creating the Review Controller

&

app.js

Now we need to update

all the Expressions to use

this controller alias.

index.html

ng-controller="ReviewController as reviewCtrl"

<form name="reviewForm" > <b>Stars: {{review.stars}}</b>

{{review.body}}

<cite>by: {{review.author}}</cite> </blockquote>

<select ng-model="review.stars">

<option value="1">1 star</option>
 <option value="2">2 stars</option>
 . . .


</select>

<textarea ng-model="review.body"></textarea> <blockquote>

app.controller(

"ReviewController"

,

function

(){


this.review

=

{};

(92)

Using the reviewCtrl.review

app.js

index.html

ng-controller="ReviewController as reviewCtrl" reviewCtrl.

reviewCtrl.

reviewCtrl.

reviewCtrl.

reviewCtrl.

<form name="reviewForm" > <blockquote>

<b>Stars: {{ review.stars}}</b> {{ review.body}}

<cite>by: {{ review.author}}</cite> </blockquote>

<select ng-model=" review.stars"> <option value="1">1 star</option>


<option value="2">2 stars</option>
 . . .


</select>

<textarea ng-model=" review.body"></textarea>

app.controller(

"ReviewController"

,

function

(){


this.review

=

{};

(93)

Using ng-submit to make the Form Work

^

app.js

index.html

ng-submit="reviewCtrl.addReview(product)"

We need to define

this function.

ng-submit

allows us to call a function when the form is submitted.

app.controller(

"ReviewController"

,

function

(){


this.review

=

{};

});

reviewCtrl. reviewCtrl.

reviewCtrl.

ng-controller="ReviewController as reviewCtrl"

<form name="reviewForm" <blockquote>

<b>Stars: {{ review.stars}}</b> {{ review.body}}

<cite>by: {{ review.author}}</cite> </blockquote>

(94)

reviewCtrl.

app.js

index.html

ng-controller="ReviewController as reviewCtrl" reviewCtrl.

reviewCtrl.

ng-submit="reviewCtrl.addReview(product)"

Push

review

onto this

product’s

reviews

array.

app.controller(

"ReviewController"

,

function

(){


this.review

=

{};

});

this

.addReview

=

function

(

product

) {

product.reviews.

push

(

this

.review);

};

<form name="reviewForm" <blockquote>

<b>Stars: {{ review.stars}}</b> {{ review.body}}

<cite>by: {{ review.author}}</cite> </blockquote>

(95)

Now with Reviews!

Review gets added,

but the form still has

all previous values!

(96)

<form name="reviewForm" ng-controller="ReviewController as reviewCtrl"

ng-submit="reviewCtrl.addReview(product)"> <blockquote>

<b>Stars: {{reviewCtrl.review.stars}}</b> {{reviewCtrl.review.body}}

<cite>by: {{reviewCtrl.review.author}}</cite>

</blockquote>

Resetting the Form on Submit

app.js

index.html

Clear out the review, so the form will reset.

app.controller("ReviewController", function(){


this.review = {};

});

this.addReview = function(product) {

product.reviews.push(this.review);

(97)

This Time the Form Resets

However, if we refresh,

the reviews get reset!


We’re not saving the

(98)
(99)

Turns out Angular has some great client side validations we can

use with our directives.

(100)

Our Old Form Code

index.html

<form name="reviewForm" ng-controller="ReviewController as reviewCtrl" ng-submit="reviewCtrl.addReview(product)">

<select ng-model="reviewCtrl.review.stars"

<option value="1">1 star</option>


...


</select>

<textarea name="body" ng-model="reviewCtrl.review.body"></textarea> <label>by:</label>

<input name="author" ng-model="reviewCtrl.review.author" type="email" /> <input type="submit" value="Submit" />


</form>

(101)

Now with validation

.

index.html

required novalidate

required required

Turn Off Default HTML Validation

Mark Required Fields

Print Forms Validity

<div> reviewForm is {{reviewForm.$valid}} </div>

<form name="reviewForm" ng-controller="ReviewController as reviewCtrl"

ng-submit="reviewCtrl.addReview(product)" >

<select ng-model="reviewCtrl.review.stars"

<option value="1">1 star</option>


...


</select>

>

<textarea name="body" ng-model="reviewCtrl.review.body" ></textarea> <label>by:</label>

<input name="author" ng-model="reviewCtrl.review.author" type="email" /> <input type="submit" value="Submit" />


(102)

With validations

We don’t want the

form to submit

(103)

<form name="reviewForm" ng-controller="ReviewController as reviewCtrl"

ng-submit="reviewCtrl.addReview(product)" novalidate>

Preventing the Submit

index.html

We only want this method to be called

if

reviewForm.$valid

is true.

(104)

<form name="reviewForm" ng-controller="ReviewController as reviewCtrl"

ng-submit="reviewForm.$valid && reviewCtrl.addReview(product)" novalidate>

Preventing the Submit

index.html

If valid is

false

, then

addReview

is

never called.

(105)

Doesn’t Submit an Invalid Form

How might we give a hint to the user

why their form is invalid?

(106)

The Input Classes

index.html

Source before typing email

<

input

name

=

"author"

ng-model

=

"reviewCtrl.review.author"

type

=

"email"

required

/>

<

input

name

=

"author"

. . . class

=

"ng-pristine ng-invalid"

>

Source after typing, with invalid email

<

input

name

=

"author"

. . .

class

=

"ng-dirty ng-invalid"

>

Source after typing, with valid email

<

input

name

=

"author"

. . .

class

=

"ng-dirty ng-valid"

>

So, let’s highlight the form field using classes after we start typing,

showing if a field is valid or invalid.

ng-valid

ng-invalid

(107)

.

ng-invalid

.

ng-dirty

{


border-color

:

#FA787E

;


}

!

.

ng-valid

.

ng-dirty

{


border-color

:

#78FA89

;


}

The classes

index.html

style.css

Red border for invalid

Green border for valid

(108)
(109)

Web forms usually have rules around valid input:

• Angular JS has built-in validations for common input types:

HTML5-based type validations

<

input

type

=

"email"

name

=

"email"

>

min

=

1

max

=

10

Can also define min

& max with numbers

<

input

type

=

"url"

name

=

"homepage"

>

(110)
(111)
(112)

Shaping Up with Angular JS

Level 4: Creating a Directive with an

(113)

Decluttering our Code

index.html

We’re going to have multiple pages that want to reuse this HTML

snippet.

How do we eliminate this duplication?

<ul

class=

"list-group"

>

<

li

class

=

"list-group-item"

ng-repeat

=

"product in store.products"

>

<h3>

{{product.name}}

<

em

class

=

"pull-right"

>

${{product.price}}

</

em

>

</h3>

<section ng-controller=

"PanelController as panel"

>

(114)

Using

ng-include for Templates

index.html

product-title.html

<h3 ng-include="'product-title.html'" class="ng-scope">


<span class="ng-scope ng-binding">Awesome Multi-touch Keyboard</span>
 <em class="pull-right ng-scope ng-binding">$250.00</em>


</h3>

generated html

ng-include

is expecting a variable with the name of the file to include.


To pass the name directly as a string, use single quotes

('...')

<ul class="list-group">


<li class="list-group-item" ng-repeat="product in store.products"> <h3 ng-include="'product-title.html'"

name of file to include

</h3>

<section ng-controller="PanelController as panel">

>

{{product.name}}

(115)
(116)

Web Server

HTML JavaScript

Response with Webpage & Assets

Web Browser

URL Request to server

HTML Returned

Fetches ng-included file

HTML

Browser loads up

Angular app.

(117)

<h3

ng-include=

"'product-title.html'"

></h3>

Creating our First Custom Directive

index.html

Custom Directive

Using ng-include...

Our old code and our custom Directive will do the same thing...

with some additional code.

<product-title></product-title>

index.html

(118)

Why Directives?

Directives allow you to write HTML that expresses the behavior

of your application.

Can you

tell what

this doe

s?

<aside class="col-sm-3">


<book-cover></book-cover>


<h4><book-rating></book-rating></h4>


</aside>


<div class="col-sm-9">


<h3><book-title></book-title></h3>
 
 <book-authors></book-authors>
 
 <book-review-text></book-review-text>
 
 <book-genres></book-genres>
 </div>

(119)

Template-expanding Directives are the simplest:

• define a custom tag or attribute that is expanded or replaced

• can include Controller logic, if needed

Writing Custom Directives

Directives can also be used for:

•Expressing complex UI

•Calling events and registering event handlers

•Reusing common components

(120)

app.directive(

'productTitle'

,

function

(){


return

{

!

};


});

How to Build Custom Directives

app.js

<product-title></product-title>

index.html

References

Related documents

ADC is the analog to digital converter, and Gvc(z) is the controller that takes into account the mean value of the output voltage, which in our case generates k, that is

It is concluded that a significant contingent factor is the overall SC configuration, which should be considered in the process of evaluating investments in improvement

The information, reports, financial models, forecasts, strategies, audio broadcasts and other media (referred to as “Content” throughout this Legal Notice), provided on this web

On the basis of clarifying theoretical and practical matters of the timber industry, legal aspect, as well as making predictions about the opportunities and

NLRP3 inflammasome activation in retinal pigment epithelial cells by lysosomal destabilization: implications for age-related macular degeneration. Tarallo V, Hirano Y, Gelfand BD,

{ use clause use clause ( to ( to include other include other package) package) type declaration type declaration type declaration type declaration subtype declaration

When your employment with Temple University ends, or your eligibility for coverage otherwise terminates because you are no longer a member of an eligible group, benefits under

Palamatic integrates into its production line designs equipment to meet the constraints of traceability, precision dosing, mixing quality and high production rates.. From the