Transcript
Page 1: Angular.js Fundamentals

@markbates

Page 2: Angular.js Fundamentals

@markbates

Page 3: Angular.js Fundamentals
Page 4: Angular.js Fundamentals
Page 5: Angular.js Fundamentals

FLUENT2014www.metacasts.tv

Page 6: Angular.js Fundamentals

www.angularmasterclass.com

Page 7: Angular.js Fundamentals

Angular Fundamentals

Page 8: Angular.js Fundamentals

Enough Angular to be Dangerous!

Page 9: Angular.js Fundamentals

What Will Cover?

Page 10: Angular.js Fundamentals

What Will Cover?**hopefully

Page 11: Angular.js Fundamentals

• Controllers!

• ngRoute!

• Templates!

• ngResource!

• Directives!

• Filters!

• Scope!

• Testing!

• Code Organization!

• Best Practices

Page 12: Angular.js Fundamentals

Part 1• Features/Why

Angular?!

• Getting Started/Setting Up!

• Directives, Filters, and Data Binding!

• Controllers, Templates, and Scope!

• Modules!

• Routing!

• Custom Directives and Event Handling!

• Testing

Page 13: Angular.js Fundamentals

Part 2

We Code!

Page 14: Angular.js Fundamentals

Part 1

Page 15: Angular.js Fundamentals

Features

Page 16: Angular.js Fundamentals

Features• Plain JavaScript

• Data Binding

• Routing/PushState

• Testing

• Templates/Directives/Controllers

• Modular

• Dependency Injection

• jqLite

• Lightweight

Page 17: Angular.js Fundamentals

Why Angular?

Page 18: Angular.js Fundamentals

Philosophies

Page 19: Angular.js Fundamentals

Backbone.js“minimal set of data-structure and view primitives

for building web application with JavaScript”

Page 20: Angular.js Fundamentals

Ember“framework for creating ambitious web applications”

Page 21: Angular.js Fundamentals

AngularJS“Toolset for building the framework

most suited to your application development”

Page 22: Angular.js Fundamentals
Page 23: Angular.js Fundamentals
Page 24: Angular.js Fundamentals

Weight

Page 25: Angular.js Fundamentals

“production” versions (minified) w/ required dependencies

Page 26: Angular.js Fundamentals

AngularJS Ember Backbone.js

base 109kb 264kb 6.5kb

templating language built-in

90kb (handlebars) ??

data adapter built-in75kb

(ember-data)84kb

(jQuery)

support N/A 84kb (jQuery)

17kb (json2.js)

5.0kb (underscore.js

)

109kb 513kb 112.5kb

Page 27: Angular.js Fundamentals

Mindshare

Page 28: Angular.js Fundamentals

Google

Page 29: Angular.js Fundamentals

AngularJS Backbone.js Ember

Watchers 2,155 1,442 824

Stars 21,408 17,291 9,570

Forks 6,670 3,783 2,044

Github

Page 30: Angular.js Fundamentals

“Basic” Models

Page 31: Angular.js Fundamentals

Backbone.jsclass  App.Beer  extends  Backbone.Model      class  App.Beers  extends  Backbone.Collection  !  model:  Beer

Page 32: Angular.js Fundamentals

EmberApp.Beer  =  DS.Model.extend      title:  DS.attr("string")      abv:  DS.attr("number")      country_id:  DS.attr("number")      brewery_id:  DS.attr("number")      brewery:  DS.belongsTo("App.Brewery")      country:  DS.belongsTo("App.Country")

Page 33: Angular.js Fundamentals

AngularJSApp.Beer  =  {}

Page 34: Angular.js Fundamentals

“Remote” Models

Page 35: Angular.js Fundamentals

Backbone.jsclass  App.Beer  extends  Backbone.Model      urlRoot:  "/api/v1/beers"        class  App.Beers  extends  Backbone.Collection          url:  -­‐>          if  @brewery_id?              return  "/api/v1/breweries/#{@brewery_id}/beers"          else              return  "/api/v1/beers"          model:  Beer

Page 36: Angular.js Fundamentals

EmberApp.Beer  =  DS.Model.extend      title:  DS.attr("string")      abv:  DS.attr("number")      country_id:  DS.attr("number")      brewery_id:  DS.attr("number")      brewery:  DS.belongsTo("App.Brewery")      country:  DS.belongsTo("App.Country")

Page 37: Angular.js Fundamentals

EmberDS.RESTAdapter.reopen      namespace:  'api/v1'      App.Store  =  DS.Store.extend      revision:  14      adapter:  DS.RESTAdapter.create()

Page 38: Angular.js Fundamentals

AngularJSApp.factory  "Beer",  ($resource)  -­‐>      return  $resource  "/api/v1/beers/:id",                                        {id:  "@id"},                                        {update:  {method:  "PUT"}}

Page 39: Angular.js Fundamentals

Routers

Page 40: Angular.js Fundamentals

Backbone.js@Router  =  Backbone.Router.extend          initialize:  -­‐>          @countries  =  new  Countries()          routes:          "breweries/:brewery_id":  "brewery"          "breweries/:brewery_id/edit":  "breweryEdit"          brewery:  (brewery_id)  -­‐>          @changeView(new  BreweryView(collection:  @countries,  model:  new  Brewery(id:  brewery_id)))          breweryEdit:  (brewery_id)  -­‐>          @changeView(new  BreweryEditView(collection:  @countries,  model:  new  Brewery(id:  brewery_id)))          changeView:  (view)  =>          @currentView?.remove()          @currentView  =  view          $("#outlet").html(@currentView.el)

Page 41: Angular.js Fundamentals

Ember

App.Router.map  -­‐>      @resource  "brewery",  {path:  "brewery/:brewery_id"}

Page 42: Angular.js Fundamentals

EmberApp.BreweryRoute  =  Ember.Route.extend      model:  (params)-­‐>          App.Brewery.find(params.brewery_id)

Page 43: Angular.js Fundamentals

AngularJSApp.config  ($routeProvider)  -­‐>          $routeProvider          .when("/breweries/:id",  {              templateUrl:  "/assets/brewery.html",              controller:  "BreweryController"          })          .when("/breweries/:id/edit",  {              templateUrl:  "/assets/edit_brewery.html",              controller:  "EditBreweryController"          })

Page 44: Angular.js Fundamentals

Controllers/Views

Page 45: Angular.js Fundamentals

Backbone.jsclass  @BreweryEditView  extends  Backbone.View          template:  "brewery_edit"          events:          "click  #save-­‐button":  "saveClicked"          "keypress  #brewery-­‐title":  "titleEdited"          initialize:  -­‐>          super          @countriesView  =  new  CountriesView(collection:  @collection)          @$el.html(@countriesView.el)          @model.on  "change",  @render          @model.fetch()          render:  =>          @$("#country-­‐outlet").html(@renderTemplate())          return  @

   saveClicked:  (e)  =>          e?.preventDefault()          attrs  =              title:  @$("#brewery-­‐title").val()              synonyms:  @$("#brewery-­‐synonyms").val()              address:  @$("#brewery-­‐address").val()          @model.save  attrs,              success:  (model,  response,  options)  =>                  App.navigate("/breweries/#{@model.id}",  trigger:  true)              error:  (model,  xhr,  options)  -­‐>                  errors  =  []                  for  key,  value  of  xhr.responseJSON.errors                      errors.push  "#{key}:  #{value.join(",  ")}"                  alert  errors.join("\n")          titleEdited:  (e)  =>          title  =  @$("#brewery-­‐title").val()          @$("h2").text(title)  !    #  further  code  omitted

Page 46: Angular.js Fundamentals

EmberApp.BreweryController  =  Ember.ObjectController.extend        save:  -­‐>          @store.commit()          #  further  code  omitted

Page 47: Angular.js Fundamentals

AngularJS@EditBreweryController  =  ($scope,  $routeParams,  $location,  Brewery)  -­‐>          $scope.brewery  =  Brewery.get(id:  $routeParams.id)          $scope.save  =  -­‐>          success  =  -­‐>              $location.path("/breweries/#{$routeParams.id}")              $scope.errors  =  null          failure  =  (object)-­‐>              $scope.errors  =  object.data.errors          $scope.brewery.$update  {},  success,  failure

Page 48: Angular.js Fundamentals

Templates

Page 49: Angular.js Fundamentals

Backbone.js<h2><%=  @model.displayName()  %></h2>      <form>          <div  class="control-­‐group">          <label  class="control-­‐label"  for="title">Title</label>          <div  class="controls">              <input  type='text'  class='input-­‐xxlarge'  value='<%=  @model.get("title")  %>'id='brewery-­‐title'>          </div>      </div>          <div  class="control-­‐group">          <label  class="control-­‐label"  for="synonyms">Synonyms</label>          <div  class="controls">              <input  type='text'  class='input-­‐xxlarge'  value='<%=  @model.get("synonyms")  %>'id='brewery-­‐synonyms'>          </div>      </div>          <div  class="control-­‐group">          <label  class="control-­‐label"  for="address">Address</label>          <div  class="controls">              <textarea  class='input-­‐xxlarge'  id='brewery-­‐address'><%=  @model.get("address")  %></textarea>          </div>      </div>          <button  class='btn  btn-­‐primary'  id='save-­‐button'>Save</button>      <a  href="/breweries/<%=  @model.id  %>"  class='btn'>Cancel</a>      </form>

Page 50: Angular.js Fundamentals

Backbone.js<h2><%=  @model.displayName()  %></h2>  

   

<form>  

   

   <div  class="control-­‐group">  

       <label  class="control-­‐label"  for="title">Title</label>  

       <div  class="controls">  

           <input  type='text'  class='input-­‐xxlarge'  value='<%=  @model.get("title")  %>'id='brewery-­‐title'>          </div>  

   </div>  

   

   <div  class="control-­‐group">  

       <label  class="control-­‐label"  for="synonyms">Synonyms</label>  

       <div  class="controls">  

           <input  type='text'  class='input-­‐xxlarge'  value='<%=  @model.get("synonyms")  %>'id='brewery-­‐synonyms'>  

       </div>  

   </div>  

   

   <div  class="control-­‐group">  

       <label  class="control-­‐label"  for="address">Address</label>  

       <div  class="controls">  

           <textarea  class='input-­‐xxlarge'  id='brewery-­‐address'><%=  @model.get("address")  %></textarea>  

       </div>  

   </div>  

   

   <button  class='btn  btn-­‐primary'  id='save-­‐button'>Save</button>  

   <a  href="/breweries/<%=  @model.id  %>"  class='btn'>Cancel</a>  

   

</form>

Page 51: Angular.js Fundamentals

Backbone.js<h2><%=  @model.displayName()  %></h2>  

   

<form>  

   

   <div  class="control-­‐group">  

       <label  class="control-­‐label"  for="title">Title</label>  

       <div  class="controls">  

           <input  type='text'  class='input-­‐xxlarge'  value='<%=  @model.get("title")  %>'id='brewery-­‐title'>  

       </div>  

   </div>  

   

   <div  class="control-­‐group">  

       <label  class="control-­‐label"  for="synonyms">Synonyms</label>  

       <div  class="controls">  

           <input  type='text'  class='input-­‐xxlarge'  value='<%=  @model.get("synonyms")  %>'id='brewery-­‐synonyms'>  

       </div>  

   </div>  

   

   <div  class="control-­‐group">  

       <label  class="control-­‐label"  for="address">Address</label>  

       <div  class="controls">  

           <textarea  class='input-­‐xxlarge'  id='brewery-­‐address'><%=  @model.get("address")  %></textarea>          </div>  

   </div>  

   

   <button  class='btn  btn-­‐primary'  id='save-­‐button'>Save</button>  

   <a  href="/breweries/<%=  @model.id  %>"  class='btn'>Cancel</a>  

   

</form>

Page 52: Angular.js Fundamentals

<div  class='span12'>  

   <h2>{{displayName}}</h2>  

   <h3>  

       {{cityState}}  

       {{#linkTo  "country"  country}}  

           {{country.title}}  

       {{/linkTo}}  

   </h3>  

   {{#if  isEditing}}  

       <form>  

   

           <div  class="control-­‐group">  

               <label  class="control-­‐label"  for="title">Title</label>  

               <div  class="controls">  

                   {{view  Ember.TextField  valueBinding="title"  class='input-­‐xxlarge'}}  

               </div>  

           </div>  

   

           <div  class="control-­‐group">  

               <label  class="control-­‐label"  for="synonyms">Synonyms</label>  

               <div  class="controls">  

                   {{view  Ember.TextField  valueBinding="synonyms"  class='input-­‐xxlarge'}}  

               </div>  

           </div>  

   

           <div  class="control-­‐group">  

               <label  class="control-­‐label"  for="synonyms">Synonyms</label>  

               <div  class="controls">  

                   {{view  Ember.TextArea  valueBinding="address"  class='input-­‐xxlarge'}}  

               </div>  

           </div>  

   

           <button  class='btn  btn-­‐primary'  {{action  "save"}}>Save</button>  

   

       </form>  

   {{  else  }}  

       {{  partial  "brewery/show"  }}  

   {{/if}}  

</div>

Ember

Page 53: Angular.js Fundamentals

<div  class='span12'>  

   <h2>{{displayName}}</h2>  

   <h3>  

       {{cityState}}  

       {{#linkTo  "country"  country}}  

           {{country.title}}  

       {{/linkTo}}  

   </h3>  

   {{#if  isEditing}}  

       <form>  

   

           <div  class="control-­‐group">  

               <label  class="control-­‐label"  for="title">Title</label>  

               <div  class="controls">  

                   {{view  Ember.TextField  valueBinding="title"  class='input-­‐xxlarge'}}  

               </div>  

           </div>  

   

           <div  class="control-­‐group">  

               <label  class="control-­‐label"  for="synonyms">Synonyms</label>  

               <div  class="controls">  

                   {{view  Ember.TextField  valueBinding="synonyms"  class='input-­‐xxlarge'}}  

               </div>  

           </div>  

   

           <div  class="control-­‐group">  

               <label  class="control-­‐label"  for="synonyms">Synonyms</label>  

               <div  class="controls">  

                   {{view  Ember.TextArea  valueBinding="address"  class='input-­‐xxlarge'}}  

               </div>  

           </div>  

   

           <button  class='btn  btn-­‐primary'  {{action  "save"}}>Save</button>  

   

       </form>  

   {{  else  }}  

       {{  partial  "brewery/show"  }}  

   {{/if}}  

</div>

Ember

Page 54: Angular.js Fundamentals

<div  class='span12'>  

   <h2>{{displayName}}</h2>  

   <h3>  

       {{cityState}}  

       {{#linkTo  "country"  country}}  

           {{country.title}}  

       {{/linkTo}}  

   </h3>  

   {{#if  isEditing}}  

       <form>  

   

           <div  class="control-­‐group">  

               <label  class="control-­‐label"  for="title">Title</label>  

               <div  class="controls">  

                   {{view  Ember.TextField  valueBinding="title"  class='input-­‐xxlarge'}}  

               </div>  

           </div>  

   

           <div  class="control-­‐group">  

               <label  class="control-­‐label"  for="synonyms">Synonyms</label>  

               <div  class="controls">  

                   {{view  Ember.TextField  valueBinding="synonyms"  class='input-­‐xxlarge'}}  

               </div>  

           </div>  

   

           <div  class="control-­‐group">  

               <label  class="control-­‐label"  for="synonyms">Synonyms</label>  

               <div  class="controls">  

                   {{view  Ember.TextArea  valueBinding="address"  class='input-­‐xxlarge'}}  

               </div>  

           </div>  

           <button  class='btn  btn-­‐primary'  {{action  "save"}}>Save</button>  

       </form>  

   {{  else  }}  

       {{  partial  "brewery/show"  }}  

   {{/if}}  

</div>

Ember

Page 55: Angular.js Fundamentals

<form>  

   <h3>{{brewery.title}}</h3>  

   <div  ng-­‐include='"/assets/_errors.html"'></div>  

   <div  class="control-­‐group">  

       <label  class="control-­‐label"  for="title">Title</label>  

       <div  class="controls">  

           <input  type='text'  class='input-­‐xxlarge'  ng-­‐

model='brewery.title'>  

       </div>  

   </div>  

   

   <div  class="control-­‐group">  

       <label  class="control-­‐label"  for="synonyms">Synonyms</label>  

       <div  class="controls">  

           <input  type='text'  class='input-­‐xxlarge'  ng-­‐

model='brewery.synonyms'>  

       </div>  

   </div>  

   

   <div  class="control-­‐group">  

       <label  class="control-­‐label"  for="address">Address</label>  

       <div  class="controls">  

           <textarea  class='input-­‐xxlarge'  ng-­‐model='brewery.address'></

textarea>  

       </div>  

   </div>  

   

   <button  class='btn  btn-­‐primary'  ng-­‐click='save()'>Save</button>  

   

</form>

AngularJS

Page 56: Angular.js Fundamentals

AngularJS<form>  

   <h3>{{brewery.title}}</h3>  

   <div  ng-­‐include='"/assets/_errors.html"'></div>  

   <div  class="control-­‐group">  

       <label  class="control-­‐label"  for="title">Title</label>  

       <div  class="controls">  

           <input  type='text'  class='input-­‐xxlarge'  ng-­‐model='brewery.title'>  

       </div>  

   </div>  

   

   <div  class="control-­‐group">  

       <label  class="control-­‐label"  for="synonyms">Synonyms</label>  

       <div  class="controls">  

           <input  type='text'  class='input-­‐xxlarge'  ng-­‐model='brewery.synonyms'>  

       </div>  

   </div>  

   

   <div  class="control-­‐group">  

       <label  class="control-­‐label"  for="address">Address</label>  

       <div  class="controls">  

           <textarea  class='input-­‐xxlarge'  ng-­‐model='brewery.address'></textarea>  

       </div>  

   </div>  

   

   <button  class='btn  btn-­‐primary'  ng-­‐click='save()'>Save</button>  

   

</form>

Page 57: Angular.js Fundamentals

<form>  

   <h3>{{brewery.title}}</h3>  

   <div  ng-­‐include='"/assets/_errors.html"'></div>  

   <div  class="control-­‐group">  

       <label  class="control-­‐label"  for="title">Title</label>  

       <div  class="controls">  

           <input  type='text'  class='input-­‐xxlarge'  ng-­‐model='brewery.title'>  

       </div>  

   </div>  

   

   <div  class="control-­‐group">  

       <label  class="control-­‐label"  for="synonyms">Synonyms</label>  

       <div  class="controls">  

           <input  type='text'  class='input-­‐xxlarge'  ng-­‐model='brewery.synonyms'>  

       </div>  

   </div>  

   

   <div  class="control-­‐group">  

       <label  class="control-­‐label"  for="address">Address</label>  

       <div  class="controls">  

           <textarea  class='input-­‐xxlarge'  ng-­‐model='brewery.address'></textarea>  

       </div>  

   </div>  

   <button  class='btn  btn-­‐primary'  ng-­‐click='save()'>Save</button>  

 </form>

AngularJS

Page 58: Angular.js Fundamentals

Pros/Cons

Page 59: Angular.js Fundamentals

Backbone.js• Too simple

• Not opinionated enough

• “Memory” management

• Unstructured

• Spaghetti code

• Lightweight

• Not opinionated

• Simple

• Easy to read source

• “widget” development

Pros Cons

Page 60: Angular.js Fundamentals

Ember• Too complex

• Overly opinionated

• Heavyweight

• ember-data - not production ready (very buggy)

• Little to no mind-share outside of Rails

• Difficult to read source code

• Structured

• Highly opinionated

• “less” code

• “large” apps

Pros Cons

Page 61: Angular.js Fundamentals

AngularJS• Difficult to read source

code

• jQuery plugins require custom directives

• Large apps requiring self-imposed structure

• Lightly structured

• Lightly opinionated

• “less” code

• Plain JavaScript

• Simple/Powerful

• Easy to test

• Lightweight

• small, medium, or large apps

Pros Cons

Page 62: Angular.js Fundamentals

Getting Started

Page 63: Angular.js Fundamentals
Page 64: Angular.js Fundamentals
Page 65: Angular.js Fundamentals
Page 66: Angular.js Fundamentals
Page 67: Angular.js Fundamentals
Page 68: Angular.js Fundamentals
Page 69: Angular.js Fundamentals

5 Minute Break

Page 70: Angular.js Fundamentals

Directives, Filters, and Data Binding

Page 71: Angular.js Fundamentals

Directives<body ng-app>! <ng-view></ng-view>! <ul>! <li ng-repeat='comment in comments'>! {{comment.body}}! </li>! </ul>!</body>

Page 72: Angular.js Fundamentals

Directives<body ng-app>! <ng-view></ng-view>! <ul>! <li ng-repeat='comment in comments'>! {{comment.body}}! </li>! </ul>!</body>

Page 73: Angular.js Fundamentals

Directives<body ng-app>! <ng-view></ng-view>! <ul>! <li ng-repeat='comment in comments'>! {{comment.body}}! </li>! </ul>!</body>

Page 74: Angular.js Fundamentals

Directives<body ng-app>! <ng-view></ng-view>! <ul>! <li ng-repeat='comment in comments'>! {{comment.body}}! </li>! </ul>!</body>

Page 75: Angular.js Fundamentals

Directives<body ng-app>! <ng-view></ng-view>! <ul>! <li ng-repeat='comment in comments'>! {{comment.body}}! </li>! </ul>!</body>

Page 76: Angular.js Fundamentals

Demo

Page 77: Angular.js Fundamentals

Filters<ul>! <li ng-repeat='c in comments | orderBy:"date"'>! {{c.author | uppercase}}! </li>!</ul>

Page 78: Angular.js Fundamentals

Filters<ul>! <li ng-repeat='c in comments | orderBy:"date"'>! {{c.author | uppercase}}! </li>!</ul>

Page 79: Angular.js Fundamentals

Filters<ul>! <li ng-repeat='c in comments | orderBy:"date"'>! {{c.author | uppercase}}! </li>!</ul>

Page 80: Angular.js Fundamentals

<ul>! <li ng-repeat='c in comments | orderBy:"date"'>! {{c.author | uppercase}}! </li>!</ul>

Filters

Page 81: Angular.js Fundamentals

Demo

Page 82: Angular.js Fundamentals

Controllers, Templates, and Scope

Page 83: Angular.js Fundamentals

Controllers, Templates and Scope

Template

Page 84: Angular.js Fundamentals

Controllers, Templates and Scope

Template Controller

Page 85: Angular.js Fundamentals

Controllers, Templates and Scope

Template Controller

Page 86: Angular.js Fundamentals

Controllers, Templates and Scope

Template Controller

Page 87: Angular.js Fundamentals

Demo

Page 88: Angular.js Fundamentals

Modules

Page 89: Angular.js Fundamentals

Module

angular.module('app', []);

Page 90: Angular.js Fundamentals

Module

Config

angular.module('app', []);

Page 91: Angular.js Fundamentals

Module

Config Controller

angular.module('app', []);

Page 92: Angular.js Fundamentals

Module

Config Controller Factories

angular.module('app', []);

Page 93: Angular.js Fundamentals

Module

Config Controller Factories Directives

angular.module('app', []);

Page 94: Angular.js Fundamentals

Module

Config Controller Factories Directives Filters

angular.module('app', []);

Page 95: Angular.js Fundamentals

Module

Config Controller Factories Directives Filters

Routes

angular.module('app', []);

Page 96: Angular.js Fundamentals

Demo

Page 97: Angular.js Fundamentals

Routing

Page 98: Angular.js Fundamentals

App.config(function($routeProvider, $locationProvider) {! $locationProvider.html5Mode(true);!! $routeProvider.when('/posts', {! controller: 'PostsIndexController',! templateUrl: 'posts/index.html'! })! .when('/posts/:id',{! controller: 'PostsShowController',! templateUrl: 'posts/show.html'! })! .otherwise({! redirectTo: '/posts'! });!});

Routing

Page 99: Angular.js Fundamentals

App.config(function($routeProvider, $locationProvider) {! $locationProvider.html5Mode(true);!! $routeProvider.when('/posts', {! controller: 'PostsIndexController',! templateUrl: 'posts/index.html'! })! .when('/posts/:id',{! controller: 'PostsShowController',! templateUrl: 'posts/show.html'! })! .otherwise({! redirectTo: '/posts'! });!});

Routing

Page 100: Angular.js Fundamentals

App.config(function($routeProvider, $locationProvider) {! $locationProvider.html5Mode(true);!! $routeProvider.when('/posts', {! controller: 'PostsIndexController',! templateUrl: 'posts/index.html'! })! .when('/posts/:id',{! controller: 'PostsShowController',! templateUrl: 'posts/show.html'! })! .otherwise({! redirectTo: '/posts'! });!});

Routing

Page 101: Angular.js Fundamentals

App.config(function($routeProvider, $locationProvider) {! $locationProvider.html5Mode(true);!! $routeProvider.when('/posts', {! controller: 'PostsIndexController',! templateUrl: 'posts/index.html'! })! .when('/posts/:id',{! controller: 'PostsShowController',! templateUrl: 'posts/show.html'! })! .otherwise({! redirectTo: '/posts'! });!});

Routing

Page 102: Angular.js Fundamentals

App.config(function($routeProvider, $locationProvider) {! $locationProvider.html5Mode(true);!! $routeProvider.when('/posts', {! controller: 'PostsIndexController',! templateUrl: 'posts/index.html'! })! .when('/posts/:id',{! controller: 'PostsShowController',! templateUrl: 'posts/show.html'! })! .otherwise({! redirectTo: '/posts'! });!});

Routing

Page 103: Angular.js Fundamentals

App.config(function($routeProvider, $locationProvider) {! $locationProvider.html5Mode(true);!! $routeProvider.when('/posts', {! controller: 'PostsIndexController',! templateUrl: 'posts/index.html'! })! .when('/posts/:id',{! controller: 'PostsShowController',! templateUrl: 'posts/show.html'! })! .otherwise({! redirectTo: '/posts'! });!});

Routing

Page 104: Angular.js Fundamentals

App.config(function($routeProvider, $locationProvider) {! $locationProvider.html5Mode(true);!! $routeProvider.when('/posts', {! controller: 'PostsIndexController',! templateUrl: 'posts/index.html'! })! .when('/posts/:id',{! controller: 'PostsShowController',! templateUrl: 'posts/show.html'! })! .otherwise({! redirectTo: '/posts'! });!});

Routing

Page 105: Angular.js Fundamentals

App.config(function($routeProvider, $locationProvider) {! $locationProvider.html5Mode(true);!! $routeProvider.when('/posts', {! controller: 'PostsIndexController',! templateUrl: 'posts/index.html'! })! .when('/posts/:id',{! controller: 'PostsShowController',! templateUrl: 'posts/show.html'! })! .otherwise({! redirectTo: '/posts'! });!});

Routing

Page 106: Angular.js Fundamentals

App.config(function($routeProvider, $locationProvider) {! $locationProvider.html5Mode(true);!! $routeProvider.when('/posts', {! controller: 'PostsIndexController',! templateUrl: 'posts/index.html'! })! .when('/posts/:id',{! controller: 'PostsShowController',! templateUrl: 'posts/show.html'! })! .otherwise({! redirectTo: '/posts'! });!});

Routing

Page 107: Angular.js Fundamentals

App.config(function($routeProvider, $locationProvider) {! $locationProvider.html5Mode(true);!! $routeProvider.when('/posts', {! controller: 'PostsIndexController',! templateUrl: 'posts/index.html'! })! .when('/posts/:id',{! controller: 'PostsShowController',! templateUrl: 'posts/show.html'! })! .otherwise({! redirectTo: '/posts'! });!});

Routing

Page 108: Angular.js Fundamentals

App.config(function($routeProvider, $locationProvider) {! $locationProvider.html5Mode(true);!! $routeProvider.when('/posts', {! controller: 'PostsIndexController',! templateUrl: 'posts/index.html'! })! .when('/posts/:id',{! controller: 'PostsShowController',! templateUrl: 'posts/show.html'! })! .otherwise({! redirectTo: '/posts'! });!});

Routing

Page 109: Angular.js Fundamentals

Demo

Page 110: Angular.js Fundamentals

Custom Directives and Event Handling

Page 111: Angular.js Fundamentals

App.directive("upCaser", function() {! return {! link: function(scope, el, attrs) {! $(el).find('p').each(function(i, p) {! p = $(p);! p.text(p.text().toUpperCase());! });! }! };!});

Directives

Page 112: Angular.js Fundamentals

DirectivesApp.directive("upCaser", function() {! return {! link: function(scope, el, attrs) {! $(el).find('p').each(function(i, p) {! p = $(p);! p.text(p.text().toUpperCase());! });! }! };!});

Page 113: Angular.js Fundamentals

App.directive("upCaser", function() {! return {! link: function(scope, el, attrs) {! $(el).find('p').each(function(i, p) {! p = $(p);! p.text(p.text().toUpperCase());! });! }! };!});

Directives

Page 114: Angular.js Fundamentals

App.directive("upCaser", function() {! return {! link: function(scope, el, attrs) {! $(el).find('p').each(function(i, p) {! p = $(p);! p.text(p.text().toUpperCase());! });! }! };!});

Directives

Page 115: Angular.js Fundamentals

App.directive("upCaser", function() {! return {! link: function(scope, el, attrs) {! $(el).find('p').each(function(i, p) {! p = $(p);! p.text(p.text().toUpperCase());! });! }! };!});

Directives

Page 116: Angular.js Fundamentals

App.directive("upCaser", function() {! return {! link: function(scope, el, attrs) {! $(el).find('p').each(function(i, p) {! p = $(p);! p.text(p.text().toUpperCase());! });! }! };!});

Directives

Page 117: Angular.js Fundamentals

App.directive("upCaser", function() {! return {! link: function(scope, el, attrs) {! $(el).find('p').each(function(i, p) {! p = $(p);! p.text(p.text().toUpperCase());! });! }! };!});

Directives

Page 118: Angular.js Fundamentals

App.directive("upCaser", function() {! return {! link: function(scope, el, attrs) {! $(el).find('p').each(function(i, p) {! p = $(p);! p.text(p.text().toUpperCase());! });! }! };!});

Directives

Page 119: Angular.js Fundamentals

<div up-caser>! <p>some text</p>! <p>some other text</p>!</div>

Directives

Page 120: Angular.js Fundamentals

Directives<up-caser>! <p>some text</p>! <p>some other text</p>!</up-caser>

Page 121: Angular.js Fundamentals

App.directive("upCaser", function() {! return {! restrict: 'E',! link: function(scope, el, attrs) {! $(el).find('p').each(function(i, p) {! p = $(p);! p.text(p.text().toUpperCase());! });! }! };!});

Directives

Page 122: Angular.js Fundamentals

Directives<up-caser>! <p>some text</p>! <p>some other text</p>!</up-caser>

Page 123: Angular.js Fundamentals

App.directive("upCaser", function() {! return {! restrict: 'AEC',! link: function(scope, el, attrs) {! $(el).find('p').each(function(i, p) {! p = $(p);! p.text(p.text().toUpperCase());! });! }! };!});

Directives

Page 124: Angular.js Fundamentals

Demo

Page 125: Angular.js Fundamentals

Events

Page 126: Angular.js Fundamentals

Scope

Page 127: Angular.js Fundamentals

Events

$broadcast

$emit

Page 128: Angular.js Fundamentals

App.directive("alerter", function() {! return {! restrict: 'E',! link: function(scope, el, attrs) {! setTimeout(function() {! scope.$emit("up", "Hello Up!");! scope.$broadcast("down", "Hello Down!");! scope.$apply();! }, 3000);! }! };!});

Events

Page 129: Angular.js Fundamentals

App.directive("alerter", function() {! return {! restrict: 'E',! link: function(scope, el, attrs) {! setTimeout(function() {! scope.$emit("up", "Hello Up!");! scope.$broadcast("down", "Hello Down!");! scope.$apply();! }, 3000);! }! };!});

Events

Page 130: Angular.js Fundamentals

App.directive("alerter", function() {! return {! restrict: 'E',! link: function(scope, el, attrs) {! setTimeout(function() {! scope.$emit("up", "Hello Up!");! scope.$broadcast("down", "Hello Down!");! scope.$apply();! }, 3000);! }! };!});

Events

Page 131: Angular.js Fundamentals

App.directive("alerter", function() {! return {! restrict: 'E',! link: function(scope, el, attrs) {! setTimeout(function() {! scope.$emit("up", "Hello Up!");! scope.$broadcast("down", "Hello Down!");! scope.$apply();! }, 3000);! }! };!});

Events

Page 132: Angular.js Fundamentals

App.directive("alerter", function() {! return {! restrict: 'E',! link: function(scope, el, attrs) {! setTimeout(function() {! scope.$emit("up", "Hello Up!");! scope.$broadcast("down", "Hello Down!");! scope.$apply();! }, 3000);! }! };!});

Events

Page 133: Angular.js Fundamentals

App.directive("alerter", function() {! return {! restrict: 'E',! link: function(scope, el, attrs) {! setTimeout(function() {! scope.$emit("up", "Hello Up!");! scope.$broadcast("down", "Hello Down!");! scope.$apply();! }, 3000);! }! };!});

Events

Page 134: Angular.js Fundamentals

App.controller('SomeController', function($scope) {! $scope.$on("up", function(data, message) {! $scope.up_message = message;! });!});

Events

Page 135: Angular.js Fundamentals

App.controller('SomeController', function($scope) {! $scope.$on("up", function(data, message) {! $scope.up_message = message;! });!});

Events

Page 136: Angular.js Fundamentals

App.controller('SomeController', function($scope) {! $scope.$on("up", function(data, message) {! $scope.up_message = message;! });!});

Events

Page 137: Angular.js Fundamentals

App.controller('SomeController', function($scope) {! $scope.$on("up", function(data, message) {! $scope.up_message = message;! });!});

Events

Page 138: Angular.js Fundamentals

App.controller('SomeController', function($scope) {! $scope.$on("up", function(data, message) {! $scope.up_message = message;! });!});

Events

Page 139: Angular.js Fundamentals

App.controller('SomeController', function($scope) {! $scope.$on("up", function(data, message) {! $scope.up_message = message;! });!});

Events

Page 140: Angular.js Fundamentals

Demo

Page 141: Angular.js Fundamentals

App.controller('Main', function($scope) {! $scope.clicker = function() {! $scope.pressed = true;! };!});

Events

Page 142: Angular.js Fundamentals

App.directive("alerter", function() {! return {! restrict: 'E',! link: function(scope, el, attrs) {! scope.$watch('pressed', function() {! if (scope.pressed) {! $(el).text('Oi!');! }! });! }! };!});

Events

Page 143: Angular.js Fundamentals

App.directive("alerter", function() {! return {! restrict: 'E',! link: function(scope, el, attrs) {! scope.$watch('pressed', function() {! if (scope.pressed) {! $(el).text('Oi!');! }! });! }! };!});

Events

Page 144: Angular.js Fundamentals

Demo

Page 145: Angular.js Fundamentals

Testing

Page 146: Angular.js Fundamentals
Page 147: Angular.js Fundamentals

App.controller('FooController', function($scope) {!! $scope.setFoo = function(val) {! $scope.foo = val;! };!!});

Testing

Page 148: Angular.js Fundamentals

describe('FooController', function() {!! beforeEach(function() {module('app')});!! beforeEach(inject(function($rootScope, $controller) {! this.scope = $rootScope.$new();! $controller('FooController', {$scope: this.scope})! }));!! describe('setFoo()', function() {!! it('sets the foo value', function() {! expect(this.scope.foo).not.toBeDefined();! this.scope.setFoo('Bar');! expect(this.scope.foo).toEqual('Bar');! });! });!});

Testing

Page 149: Angular.js Fundamentals

describe('FooController', function() {!! beforeEach(function() {module('app')});!! beforeEach(inject(function($rootScope, $controller) {! this.scope = $rootScope.$new();! $controller('FooController', {$scope: this.scope})! }));!! describe('setFoo()', function() {!! it('sets the foo value', function() {! expect(this.scope.foo).not.toBeDefined();! this.scope.setFoo('Bar');! expect(this.scope.foo).toEqual('Bar');! });! });!});

Testing

Page 150: Angular.js Fundamentals

describe('FooController', function() {!! beforeEach(function() {module('app')});!! beforeEach(inject(function($rootScope, $controller) {! this.scope = $rootScope.$new();! $controller('FooController', {$scope: this.scope})! }));!! describe('setFoo()', function() {!! it('sets the foo value', function() {! expect(this.scope.foo).not.toBeDefined();! this.scope.setFoo('Bar');! expect(this.scope.foo).toEqual('Bar');! });! });!});

Testing

Page 151: Angular.js Fundamentals

describe('FooController', function() {!! beforeEach(function() {module('app')});!! beforeEach(inject(function($rootScope, $controller) {! this.scope = $rootScope.$new();! $controller('FooController', {$scope: this.scope})! }));!! describe('setFoo()', function() {!! it('sets the foo value', function() {! expect(this.scope.foo).not.toBeDefined();! this.scope.setFoo('Bar');! expect(this.scope.foo).toEqual('Bar');! });! });!});

Testing

Page 152: Angular.js Fundamentals

describe('FooController', function() {!! beforeEach(function() {module('app')});!! beforeEach(inject(function($rootScope, $controller) {! this.scope = $rootScope.$new();! $controller('FooController', {$scope: this.scope})! }));!! describe('setFoo()', function() {!! it('sets the foo value', function() {! expect(this.scope.foo).not.toBeDefined();! this.scope.setFoo('Bar');! expect(this.scope.foo).toEqual('Bar');! });! });!});

Testing

Page 153: Angular.js Fundamentals

describe('FooController', function() {!! beforeEach(function() {module('app')});!! beforeEach(inject(function($rootScope, $controller) {! this.scope = $rootScope.$new();! $controller('FooController', {$scope: this.scope})! }));!! describe('setFoo()', function() {!! it('sets the foo value', function() {! expect(this.scope.foo).not.toBeDefined();! this.scope.setFoo('Bar');! expect(this.scope.foo).toEqual('Bar');! });! });!});

Testing

Page 154: Angular.js Fundamentals

describe('FooController', function() {!! beforeEach(function() {module('app')});!! beforeEach(inject(function($rootScope, $controller) {! this.scope = $rootScope.$new();! $controller('FooController', {$scope: this.scope})! }));!! describe('setFoo()', function() {!! it('sets the foo value', function() {! expect(this.scope.foo).not.toBeDefined();! this.scope.setFoo('Bar');! expect(this.scope.foo).toEqual('Bar');! });! });!});

Testing

Page 155: Angular.js Fundamentals

describe('FooController', function() {!! beforeEach(function() {module('app')});!! beforeEach(inject(function($rootScope, $controller) {! this.scope = $rootScope.$new();! $controller('FooController', {$scope: this.scope})! }));!! describe('setFoo()', function() {!! it('sets the foo value', function() {! expect(this.scope.foo).not.toBeDefined();! this.scope.setFoo('Bar');! expect(this.scope.foo).toEqual('Bar');! });! });!});

Testing

Page 156: Angular.js Fundamentals

describe('FooController', function() {!! beforeEach(function() {module('app')});!! beforeEach(inject(function($rootScope, $controller) {! this.scope = $rootScope.$new();! $controller('FooController', {$scope: this.scope})! }));!! describe('setFoo()', function() {!! it('sets the foo value', function() {! expect(this.scope.foo).not.toBeDefined();! this.scope.setFoo('Bar');! expect(this.scope.foo).toEqual('Bar');! });! });!});

Testing

Page 157: Angular.js Fundamentals

describe('FooController', function() {!! beforeEach(function() {module('app')});!! beforeEach(inject(function($rootScope, $controller) {! this.scope = $rootScope.$new();! $controller('FooController', {$scope: this.scope})! }));!! describe('setFoo()', function() {!! it('sets the foo value', function() {! expect(this.scope.foo).not.toBeDefined();! this.scope.setFoo('Bar');! expect(this.scope.foo).toEqual('Bar');! });! });!});

Testing

Page 158: Angular.js Fundamentals

describe('FooController', function() {!! beforeEach(function() {module('app')});!! beforeEach(inject(function($rootScope, $controller) {! this.scope = $rootScope.$new();! $controller('FooController', {$scope: this.scope})! }));!! describe('setFoo()', function() {!! it('sets the foo value', function() {! expect(this.scope.foo).not.toBeDefined();! this.scope.setFoo('Bar');! expect(this.scope.foo).toEqual('Bar');! });! });!});

Testing

Page 159: Angular.js Fundamentals

Demo

Page 160: Angular.js Fundamentals

Part 2

Page 161: Angular.js Fundamentals

Setup!

Page 162: Angular.js Fundamentals

Base Project!github.com/markbates/

fluent-2014

Page 163: Angular.js Fundamentals

Node.js!http://nodejs.org

Page 164: Angular.js Fundamentals

Lineman.js!npm install -g

[email protected]

Page 165: Angular.js Fundamentals

Install Modules!npm install

Page 166: Angular.js Fundamentals

Code Time!!

Page 167: Angular.js Fundamentals

Thanks! @markbates

www.angularmasterclass.com


Top Related