Miško Hevery


  • Intel (Hardware Engineer)
  • Adobe
  • Sun
  • Google


Passion: Better software through testing

frustration

  • Project: Google Feedback
  • Google Web Toolkit (GWT)
  • 3 developers - 6 months
  • Meet: AngularJS

    • Open Source hobby project
    • Angular 0.9 - Dragon-Breath (Oktober 2010)
    • Bet: Complete rebuild in 2 weeks
    • Lost: Done in 3 weeks
    • Javascript17.000 lines -> 1000 lines
    • Google DoubleClick
    • 2 years / 3 developers
    • Angular 1.0   (june 2012)

    Angular 1.2



    > 10 teammembers

    • 5 full time developers
    • Documentation
    • Speakers
    • 364 contributors

    Stable


    Updates less often than JQuery

    Stable release and unstable release

    Unstable != Unstable 
    new features  are still subject for change

    Superheroic JavaScript MVW  Framework

     
    "AngularJS is what HTML would have been, had it been designed for building web-apps"
    "When you develop in Angular, you are  developing in a better browser!"  
    "Pretty sure that HTML6 is going under the codename  @angularjs!" 

    AngularJS?


    != library


    = Framework

    "Better Browser"



    S.P.A.


    Single Page Applications


    Why?

    • Dynamic websites/webapplications
    • Declarative templating with databinding
    • DOM manipulation != Application Logic
    • Extend HTML
    • Decouple client side from server side
    • Modular
    • Testable
    • Plain Javascript


    Forget everything you know











    About JQuery

     

    Seriously !!!

     

    Forget JQuery

    Sins with/of JQuery

    1. Don't Design Your Page, then Change it with  DOM Manipulations
    2. Don't Augment JQuery with AngularJS
    3. Always Think in Terms of Architecture
      • The View is the "Official Record"
      • Databinding
      • Distinct Model Layer
      • Seperation of concerns
      • Dependency Injection
    4. Test Driven development


    Imperative  VS  Declarative

    How VS What

    JQuery VS AngularJS

    <input id="toggleShowHide" type="checkbox">
    <div id=”specialParagraph”>
        This content will disappear and reappear if you click the checkbox above</div>     
        
    
    <script>$(function() {
    function toggle() {  
    var isChecked = $('#toggleShowHide').is(':checked');
    var specialParagraph = $('#specialParagraph');
    if (isChecked) { specialParagraph.show(); else { specialParagraph.hide(); } }
    $('#toggleShowHide').change(function() {
    toggle();
    });
    toggle();
    });
    </script>

    AngularJS


    <input ng-model="showSpecial" type="checkbox">
    <div ng-show=”showSpecial”>
        This content will disappear and reappear if you click the   checkbox above
    </div>

    Do not include JQuery



    DOM manipulation


    Do you really need a JQuery plugin?
    Wrap it within a Directive 

    BUT:
    "Conceptually, Directives are  NOT  packaged JQuery"

    It's usually easier to refactor the plugin the "Angular Way"
     



    Or is it?



    Teaching browsers new Tricks


    • Data Binding
    • Filters
    • DI (Dependency Injection)
    • Directives
    • Animations
    • HTTP/Resource (REST)

    Data Binding


    <h1> {{ person.firstname }} <h1>
    <h1 ng-bind="person.firstname > </h1>
    <p> 1 + 1 = {{ 1 + 1 }} </p>
    Plunker: Data binding
     

    Filters

    <ul>  <li ng-repeat="person in persons | orderBy: 'lastname'"       {{ person.firstname }}       , {{ person.lastname | uppercase }}  </li></ul>
    • currency
    • date
    • filter
    • json
    • limitTo
    • lowercase
    • number
    • orderBy
    • uppercase

    Dependency Injection

    /scripts/app.js
     angular.module('railsApp', ['ngRoute', 'ngResource', 'ui-bootstrap']);

    /scripts/controllers/main.js
    angular.module('railsApp')
        .controller('MainCtrl', function($scope, $routeParam, Person){
          $scope.person = Person.get($routeParams.personId);
               $scope.save = function(person){
            Person.save(person);           }});
    
    • Loose coupling
    • Testing

    Directives

    "A way to teach HTML new Tricks"
    "Create your own HTML tags"
    "Directive === Reusable Component"
    "Register Behavior"
    "Transform / Manipulate the DOM"

    Directives

    Element

     <ng-view></ng-view>

    Attribute

     <div ng-view></div>

    Class

     <div class="ng-view"><div>

    Sample

    <tabset>
      <tab ng-repeat="tab in tabs" heading="{{tab.title}}" 
              active="tab.active" disabled="tab.disabled">
        {{tab.content}}
      </tab>
    </tabset>
    

    Core Directives


    • ng-app
    • ng-controller
    • ng-include
    • ng-repeat
    • ng-switch
    • ng-view

    Display Directives


    • ng-class
    • ng-class-even
    • ng-class-odd
    • ng-cloak
    • ng-hide
    • ng-if
    • ng-show
    • ng-style

    Event Directives


    • ng-change
    • ng-checked
    • ng-click
    • ng-dblclick
    • ng-keydown|press|up
    • ng-mousedown|enter|leave|move|over|up
    • ng-selected
    • ng-submit

    Community Directives

    custom directive

    • The place for DOM manipulation
    • Pretty complex at first
    • Usually there's already a community plugin

    Don't get

    A lot is possible without custom directives!!

    Animations

     angular.module('railsApp', ['ngAnimate']);

    Resource

    • ngResource
    • Interact with RESTFul serverside data sources
    • JSON
    • Promises

    RAILS RESTful endpoint


    class PersonController < ApplicationController  def index    @persons = Person.get(params[:person])
    respond_to do |format| format.html # index.html.erb format.json { render json: @persons, root: false } end end # other actionsend

    Resource

     angular.module('railsApp', ['ngResource'])  .factory('Person', function person($resource){    return $resource('/persons/:id', {id: '@id'}{    // DEFAULT IMPLEMENTATION OF $RESOURCE
    // 'get': {method:'GET'}, // 'save': {method:'POST'}, // 'query': {method:'GET', isArray:true}, // 'remove': {method:'DELETE'}, // 'delete': {method:'DELETE'} } }

    In use

     angular.module('railsApp')  .controller('MainCtrl', function($scope, Person){    $scope.persons = Person.query();
    $scope.add = function(newPerson){ Person.save(newPerson); } }

    Application structure



    Module

    Application Level Module

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


    Module per feature

    • Users
    • Routing
    • Admin
    • Portfolio


    Angular Modules


  • angular.js
  • angular-animate
  • angular-route
  • angular-resource
  • angular-sanitize
  • angular-touch
  • angular.module('railsApp', ['ngAnimate', 'ngRoute', 'ngResource']); 


    Config

    app.js
    angular.module('railsApp', []);
    index.html
    <!DOCTYPE HTML>
    <html ng-app="railsApp">
    <head>  <title>AngularJS with Rails</title></head><body>  <h1> {{ rails.awesomeTitle }} </h1>
    <script src="scripts/vendor/angular/angular.min.js">
    <script src="scripts/app.js"></script>
    </body></html>

    View



    HTML

    Templates

    !! Declarative !!

    $scope

    $scope.person = {
    firstName: 'Jan' lastName: 'Progger' }
    controller.js
    <h1> {{ person.firstname }} </h1>
    views/main.html

    Controller

        scripts/controllers/main.js
    
    "Expose model objects and methods to the View "

    • View specific code
    • NO DOM manipulation
    angular.module('railsApp')
      .controller('MainCtrl', function ($scope, Person) {
         $scope.persons = Person.getPersons();     $scope.addPerson = function(newPerson){        Person.save(newPerson)     }
      });

    Controller as >= 1.2

    views/main.html
    <div ng-controller="MainCtrl as main">    <p> {{ main.person.firstname }} {{ main.person.firstname }} </p></div>
    scripts/controllers/main.js
     angular.module('railsApp')
      .controller('MainCtrl', function () {
    
    this.person = { firstName: 'Jan' lastName: 'Progger' } });

    Plunker: Controllers

    Routing

    • Deep Linking
    • History (back button)

    angular.module('railsApp', ['ngRoute'])
      .config(function ($routeProvider) {
        $routeProvider
          .when('/', {
            templateUrl: 'views/main.html',
            controller: 'MainCtrl'
          })      .when('/person/:name', {
            templateUrl: 'views/person.html',
            controller: 'PersonCtrl'
          })
          .otherwise({
            redirectTo: '/'
          });
      });
    Plunker: Routing

    Services

    • View independent methods
    • Singleton

    • Constant
    • Decorator
    • Factory
    • Provider
    • Service
    • Value

    Factory

    scripts/services/person.js
    angular.module('railsApp').factory('Person', function(){  var personFactory = {};  var persons = {                   '77': {                          firstName: 'Jan',                          lastName: 'Progger                        }                 }  personFactory.get = function(personId){     return persons[personId];  }  return personFactory;
    });

    Constant


    scripts/services/constants.js
    angular.module('railsApp').constant('COMPANY', 'Gino B.V.');
    angular.module('railsApp').constant('THE_ANSWER', 42);
    scripts/controllers/main.js
    angular.module('railsApp').controller('MainCtrl',                               function(COMPANY, THE_ANSWER){     console.log('Company is ' + COMPANY);     console.log('The all knowing answer is: ' + THE_ANSWER);}

    Directory structure

    • /images
    • /scripts
      • /controllers
      • /directives
      • /services
      • app.js
    • /styles
    • /views
      • main.html
      • person.html
    • index.html

    Testing


    Test Runner: Karma testrunner


    Unit Testing: Jasmine


    End-2-End testing: Protractor

    Yeoman

    angular-generator

    Bower: Package manager

    Grunt: Build tool

    Awesome workflow

    yo angular demo
      ------ 
    yo angular:controller person
      ------ 
    yo angular:route myRoute --coffee
      ------ 
    yo angular:factory myFactory --minsafe 
    
    bower update
      ------
    bower search angular
      ------
    bower install angular --save
    
    grunt test
      ----------
    grunt build
      ----------
    grunt server    
    


    • Phonegap
    • html5
    • CSS3
    • ng-touch

    Yeah great, but who else uses it?


    • Google Feedback
    • Google DoubleClick
    • PS3: Youtube browser
    • Devoxx
    • Plunker!

    Getting Started







    bennadel.com

    Questions?

    Made with Slides.com