Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Finding Truth in Angular: Explorations in Data Visualizations

Pearl Chen
October 23, 2014

Finding Truth in Angular: Explorations in Data Visualizations

At the heart of a well-architected web application there should be a clear separation between the user interface (the “view”), the business logic (the “controller”) and the driving data behind it (the “model”).

Pearl Chen uses Angular to build interactive data visualizations; she do this to both tell stories with data, and to find the truth in datasets. Aptly, a guiding principle around MVC architecture is: “The model is the truth.”

In this session, Pearl will break down how she structured a few of her visualizations, and how Angular helped her find “MVC zen”.

Objective:
Show how model-driven app architecture makes for cleaner code.

Target audience:
Web designers, web developers, data story tellers

Assumed audience knowledge:
Beyond Angular 101 knowledge

Five things the audience will learn:
Model-view-controller basics
How Angular views, controllers, directives and filters can work together with concrete examples
How a simple Angular example compares to the same thing written in jQuery
Basics of designing and developing an interactive data visualization
Tips for optimizing CSS and JS for smooth graphics performance
http://collidehalifax.com/sessions/finding-truth-in-angular-explorations-in-data-visualizations/

Pearl Chen

October 23, 2014
Tweet

More Decks by Pearl Chen

Other Decks in Technology

Transcript

  1. @PearlChen #CollideHalifax F i n d i n g T

    r u t h i n A n g u l a r go.klab.ca/collide-truth
  2. @PearlChen #CollideHalifax Te c h n o l o g

    i s t + E d u c a t o r I ’ M A … Karma Laboratory
  3. @PearlChen #CollideHalifax Ye o m a n s t u

    f f YO U M AY K N O W M E F R O M …
  4. @PearlChen #CollideHalifax H T M L 5 Ro c k

    s . c o m YO U M AY K N O W M E F R O M …
  5. @PearlChen #CollideHalifax O v e r v i e w

    A G E N D A 1. My data viz inspiration 2. Why Angular? 3. HTML animation performance
  6. @PearlChen #CollideHalifax My d e v b a c kg

    ro u n d I N S P I R AT I O N Adobe Flash with ActionScript 2 & AS3 Adobe Flex with ActionScript 3 HTML, CSS, & JS with AngularJS
  7. @PearlChen #CollideHalifax B l o g c i t y

    ( c i rc a 2 0 0 4 ) I N S P I R AT I O N
  8. @PearlChen #CollideHalifax Jo n a t h a n H

    a r r i s I N S P I R AT I O N
  9. @PearlChen #CollideHalifax T E LU S D e v i

    c e Re s o l u t i o n s C A S E S T U DY # 1 D E M O
  10. @PearlChen #CollideHalifax D e s i g n Re s

    e a rc h Te c h n i q u e s C A S E S T U DY # 2 D E M O
  11. @PearlChen #CollideHalifax W hy A n g u l a

    r? A G E N D A • decoupling / separation of concerns • 2-way data binding • encapsulation • directives • filters
  12. @PearlChen #CollideHalifax Given this JavaScript string: name  =  'Collide  2014';

    The old school way to dynamically update DOM text: <div  id="conference"></div>   document.getElementById('conference') Things got easier with the jQuery $(selector): <div  id="conference"></div>   $('#conference') Now, with Angular! <div>{{name}}</div> .textContent  =  name; .text(  name  );
  13. @PearlChen #CollideHalifax AngularJS is a JavaScript MV* framework
 but… “there

    is nothing to inherit, nothing to call, and 
 no complex life cycle for your controllers to follow. […] It really is just a better browser.” - Misko Hevery, creator of AngularJS
 Appliness (Feb issue #11)
  14. @PearlChen #CollideHalifax B e g i n n e r

    / i n t e r m e d i a t e ? W H Y A N G U L A R ? • Declarative ➞ Readable • Spaghetti code • Does a lot of heavy lifting for you • Opinionated* == good • Created with web designers in mind
  15. @PearlChen #CollideHalifax Mo r e a d v a n

    c e d ? W H Y A N G U L A R ? • Create complex web apps with less JS code. • Write code with unit testing in mind.
  16. @PearlChen #CollideHalifax Mo d e l -Vi e w -

    C o n t ro l l e r M V C R E F R E S H E R
  17. @PearlChen #CollideHalifax Model
 your application data Controller
 mediator between the

    view & model View
 a representation
 of the model data M V C R E F R E S H E R x user input database save REST result update DOM
  18. @PearlChen #CollideHalifax Mo d e l -Vi e w -W

    h a t e v e r A N G U L A R M V C L I N K Model-View-Whatever
  19. @PearlChen #CollideHalifax Model
 single object entity View
 rendered DOM w/

    data-bindings "Controller"
 classes for augmenting $scope
 with properties and business logic A N G U L A R M O D E L-V I E W-V I E W M O D E L ( M V V M ) ViewModel ( $scope / this )
 data binding API for managing model changes = Angular magic = File you define x
  20. @PearlChen #CollideHalifax Re c o m m e n d

    e d Re a d i n g M V C R E F R E S H E R
  21. @PearlChen #CollideHalifax D a t a b i n d

    i n g A N G U L A R O V E R V I E W
  22. @PearlChen #CollideHalifax 1 - w ay b i n d

    i n g D ATA B I N D I N G <input  type="text"  value="{{yourName}}">   <h1>{{yourName}}</h1> yourName   hardcoded  to  'Pearl' <h1>{{yourName}}</h2> value="{{yourName}}" Pearl Pearl 1 -WAY M E R G E D E M O
  23. @PearlChen #CollideHalifax <input  type="text"            

                               >   <h1>{{yourName}}</h1> 2 - w ay b i n d i n g D ATA B I N D I N G yourName   hardcoded  to  'Pearl' <h1>{{yourName}}</h2> value="{{yourName}}" model becomes
 single source of truth L I N K E D L I N K E D ng-­‐model="yourName" value="{{yourName}} D E M O A U T O U P D AT E S Pearl Pearl
  24. @PearlChen #CollideHalifax H T M L C o m p

    i l e r D ATA B I N D I N G Remember:
 
 the Angular compiler consumes
 the DOM
 not string templates
  25. @PearlChen #CollideHalifax O u t p u t t i

    n g v a l u e s T E M P L AT E E X P R E S S I O N S • Expressions are JavaScript-like code snippets. • Double curly brace notation
 e.g. {{simpleVariable}}  or {{object.simpleVariable}} • Evaluate and bind to primitives
 Strings, numbers, and booleans • undefined and null values will show up blank.
  26. @PearlChen #CollideHalifax F l o w c o n t

    ro l T E M P L AT E E X P R E S S I O N S • There is none! • No looping or conditionals within {{  }}. • Handle business logic with methods in a controller or via a directive.
  27. @PearlChen #CollideHalifax v s D i r e c t

    i v e e x p r e s s i o n s T E M P L AT E E X P R E S S I O N S • You might come across something like this:
 <a  ng-­‐href="img/{{username}}.jpg">Hello  {{username}}!</a> • But what about this?
 <div  ng-­‐class="{'highlight':isHighlighted}"></div> • Object literal notation
 e.g. {'stringToOutput':booleanCondition}
 e.g. {'highlight':true} • Not exactly the same as {{ }}. 
 Evaluated in the directive. Think: function parameter. D E M O
  28. @PearlChen #CollideHalifax Fro m j Q u e r y

    t o A n g u l a r C A S E S T U DY
  29. @PearlChen #CollideHalifax Re w r i t i n g

    a s i m p l e " a p p" F R O M J Q U E R Y T O A N G U L A R Going from jQuery to AngularJS D E M O
  30. @PearlChen #CollideHalifax C o m p a r i n

    g t h e c o d e F R O M J Q U E R Y T O A N G U L A R C O M PA R E
  31. @PearlChen #CollideHalifax B e n e f i t s

    F R O M J Q U E R Y T O A N G U L A R Model-driven data binding means: • descriptive state variables —> code is better at
 "self documenting" • less code needed for DOM manipulation • business logic decoupled from the view • behavioural intentions are more clear in the HTML
  32. @PearlChen #CollideHalifax G e t t i n g o

    r g a n i z e d D I R E C T I V E S • Views are for HTML output. • Directives are for DOM manipulation. • Controllers are for your business logic.
  33. @PearlChen #CollideHalifax Angular directives teach DOM elements new tricks! •

    Use directives to enhance existing elements
 <div  ng-­‐class="{'highlight':isSelected}"></div> • Create directives to encapsulate DOM functionality
 <date-­‐picker></date-­‐picker> W h a t i s a d i r e c t i v e ? D I R E C T I V E S
  34. @PearlChen #CollideHalifax Us i n g d i r e

    c t i v e s D I R E C T I V E S Syntax-wise, it can be a: • tag attribute
 <div  ng-­‐show="isTrue"></div>
 <div  ng-­‐non-­‐bindable></div>   • existing or custom HTML tag
 <form></form>
 <date-­‐picker></date-­‐picker> • css class
 <li  class="ng-­‐class-­‐even"></li>
 <li  class="ng-­‐class-­‐odd"></li>
  35. @PearlChen #CollideHalifax B u i l t - i n

    d i r e c t i v e s D I R E C T I V E S Control • ng-repeat • ng-if / ng-switch Events • ng-click / ng-submit • ng-focus / ng-blur • ng-cut / ng-copy / ng-paste These are only some of them! Go to docs.angularjs.org/api/ng/directive for the full list. CSS • ng-class / ng-style • ng-show / ng-hide • ng-class-even / ng-class-odd Forms • form / input / select / textarea • ng-model • ng-selected / ng-checked • ng-required / ng-disabled
  36. @PearlChen #CollideHalifax E x a m p l e :

    D 3 D I R E C T I V E S From odiseo.net/angularjs/proper-use-of-d3-js-with-angular-directives: <div  ng-­‐app="myApp"  ng-­‐controller="Ctrl">      <bars-­‐chart  chart-­‐data="myData"></bars-­‐chart>   </div>
  37. @PearlChen #CollideHalifax E x a m p l e :

    C h a r t J S D I R E C T I V E S From blog.safaribooksonline.com/2013/11/07/creating-an-angularjs-component/: <chart-­‐js  id="chart1"            width="chart.width"            height="chart.height"            title="{{chart.title}}"            type="{{chart.type}}"          data="{{chart.data}}"          ng-­‐model="chart">   </chart-­‐js>
  38. @PearlChen #CollideHalifax D e f i n i n g

    c u s t o m d i r e c t i v e s C U S T O M D I R E C T I V E S • angular.module('demoApp')
    .directive('myTooltip',  function  ()  {
        return  directiveObject;
 });
  39. @PearlChen #CollideHalifax D i r e c t i v

    e d e f i n i t i o n o b j e c t C U S T O M D I R E C T I V E S
  40. @PearlChen #CollideHalifax D i r e c t i v

    e d e f i n i t i o n o b j e c t C U S T O M D I R E C T I V E S table from "AngularJS"
  41. @PearlChen #CollideHalifax To p 5 p ro p e r

    t i e s C U S T O M D I R E C T I V E S • restrict: 'E', 'A', 'C', or 'M' (or a combo 'AC') • template: '<div>Stuff</div>'
 or templateUrl: 'myTemplate.html'   • link: function  link(scope,  elem,  attrs)  {
              //  do  scope.stuff  here
          } • scope: false (default), true, or {attribute:'@=&'}   • require: directive-­‐name  with optional ^ or ?
  42. @PearlChen #CollideHalifax Re s t r i c t C

    U S T O M D I R E C T I V E S • tag attribute
 restrict:  'A'   • existing or custom HTML element
 restrict:  'E' • css class
 restrict:  'C'   • HTML comment
 restrict:  'M'   • Combine them
 restrict:  'AC'
  43. @PearlChen #CollideHalifax Te m p l a t e s

    C U S T O M D I R E C T I V E S • HTML string defined within directive
 template:  '<div>This  is  my  simple  component</div>'   • HTML fragment in external file
 templateUrl:  'views/phaseNavigator.html'
 
 In phaseNavigator.html:
 <div  class="phase-­‐navigator">
    <!-­‐-­‐  lots  of  stuff  -­‐-­‐>      
 </div>
  44. @PearlChen #CollideHalifax L i n k C U S T

    O M D I R E C T I V E S • Any DOM manipulation goes in here
 link:  function  link(scope,  elem,  attrs)  {
                //  do  scope.stuff  here  (like  a  controller  class)
            }   • scope is an Angular scope object. • element is the jqLite-wrapped element that this directive matches. • attrs is a hash object with key-value pairs of normalized attribute names and their corresponding attribute values.
  45. @PearlChen #CollideHalifax S c o p e C U S

    T O M D I R E C T I V E S <nametag name="pearl"></nametag> • inherit parent scope (default)
 scope:  false   • create an isolated scope (best method)
 scope:  {}
  46. @PearlChen #CollideHalifax Re q u i r e C U

    S T O M D I R E C T I V E S • directive name
 require:  'myOtherDirective'   • walk up the DOM to parent node
 require:  '^' • optional (aka don't throw a fit if not found)
 require:  '?'
  47. @PearlChen #CollideHalifax P r a c t i c e

    m a ke s p e r fe c t D I R E C T I V E S Dave Smith - Deep Dive into Custom Directives - NG-Conf 2014
  48. @PearlChen #CollideHalifax $ w a t c h a n

    d $ a p p l y D I R E C T I V E S TA L K I N G TO E A C H OT H E R
  49. @PearlChen #CollideHalifax $ w a t c h $ WATC

    H A N D $ A P P LY Listen for changes in your properties: scope.$watch('watchExpression',  function(){
    //  do  stuff  now  that  watchProperty  has  changed
 }); D O C S
  50. @PearlChen #CollideHalifax $ w a t c h $ WATC

    H A N D $ A P P LY Example, state changes in one file:
 scope.filterByTop10  =  function(event){
    event.preventDefault();
    scope.showInPhase  =  '';  //clear  out  phase  filters
    scope.showTop10  =  true;
 }; Listening for the change:
 scope.$watch('showTop10',  function(){
    if  (  scope.appendix.length  >  0  )  {
        scope.filteredAppendix  =  $filter('masterTechniqueFilter')
                                            (scope.appendix,  scope.showInPhase,  scope.showTop10);
    }
 });
  51. @PearlChen #CollideHalifax $ a p p l y $ WATC

    H A N D $ A P P LY Use $apply to execute an expression in angular from outside of the angular framework. scope.$apply('expression');   e.g. browser DOM events, setTimeout, XHR or third party libraries D O C S
  52. @PearlChen #CollideHalifax $ a p p l y $ WATC

    H A N D $ A P P LY Example DOM event: element.on('mouseover',  'li',  function(event){
    var  technique  =  angular.element(  event.target  ).scope().technique;
    scope.$apply(function(){
        scope.selectedTechnique  =  technique;
    });
 });
  53. @PearlChen #CollideHalifax D e f i n i n g

    a n d c a l l i n g F I LT E R S Defining a filter
 angular.module('infographicApp')
    .filter('removeZeroPixelDevices',  function  ()  {
        return  function  (devicesArray)  {
            return  _.filter(  devicesArray,  function(device){
                return  device.pxWidth  !==  0  &&  device.pxHeight  !==  0;
            });
        };
    }); Calling it
 $scope.mobileDevicesAll  =  
    $filter(  'removeZeroPixelDevices'  )(  $scope.devicesOriginal  );
  54. @PearlChen #CollideHalifax H T M L A n i m

    a t i o n s P E R F O R M A N C E
  55. H T M L To u c h S l

    i d e r C S S V S J AVA S C R I P T “This is the best mobile touch slider I’ve ever used. I’m trying to break it but I can’t!” ! - some guy at a Dribble meet up
  56. j Q u e r y . a n i

    m a t e ( ) A N I M AT I O N S T H E J AVA S C R I P T WAY EXAMPLE 
 $('div').animate(  
                                    {left:  targetX},    //  properties
                                    200,                            //  duration
                                    ‘swing’,                    //  easing
                                    function  done(){}  //  callback
                                ); CSS 
 div  {
    position:  relative;  /*or  ‘fixed’  or  ‘absolute’,  just  not  ‘static’*/
    left:  0;
 }
  57. GPU
 (graphics processing unit) • Specialized video and 3D graphics

    renderer. • Designed for doing repetitive screen updates (“paints”). • “Hardware accelerated”. CPU
 (central processing unit) • Controls all running computer software. • Better at making decisions and giving out orders. C P U v s G P U G E T T I N G S M O O T H A N I M AT I O N S
  58. • General layout compositing • CSS3 transitions • CSS3 3D

    transforms • Canvas Drawing • WebGL 3D Drawing G E T T I N G S M O O T H A N I M AT I O N S W h a t c a n g o t o t h e G P U ? Further resources: 
 “Improving the Performance of your HTML5 App”: http://www.html5rocks.com/en/tutorials/speed/html5/
 “High Performance Animations": http://www.html5rocks.com/en/tutorials/speed/high-performance-animations/
 “Let’s Play With Hardware-Accelerated CSS“: http://mobile.smashingmagazine.com/2012/06/21/play-with-hardware-accelerated-css/
 “Why Moving Elements With Translate() Is Better Than Pos:abs Top/left”: http://www.paulirish.com/2012/why-moving-elements-with-translate-is-better-than-posabs-topleft/ ˒ CSS3 transitions (I’ve only got 30 minutes!)
  59. C S S 3 Tr a n s i t

    i o n s A N I M AT I O N S T H E C S S WAY SCSS EXAMPLE 
 div  {
    @include  single-­‐transition(  left,  200ms,  
                                                              cubic-­‐bezier(0.39,  0.575,  0.565,  1)  );
 } CSS EXAMPLE 
 div  {
    -­‐webkit-­‐transition:  left  200ms  cubic-­‐bezier(0.39,  0.575,  0.565,  1);
    -­‐moz-­‐transition:        left  200ms  cubic-­‐bezier(0.39,  0.575,  0.565,  1);
    transition:                  left  200ms  cubic-­‐bezier(0.39,  0.575,  0.565,  1);
 } JQUERY (at the point you need the div animated) 
 $('div').css(  {left:  targetX}  );
          //  .addClass() (Note: vendor prefixes not required for latest browsers but use for optimal backwards and mobile compatibility.)
  60. c u b i c - b e z i

    e r w h a t ? ? E A S I N G F U N C T I O N S Don’t fret! Just copy from easings.net and cubic-bezier.com:
  61. j Q u e r y . a n i

    m a t e ( ) R E C A P Cons • Lower performance since animation will run in the CPU • Additional (easy to remember) easings require jQuery UI or other easing plugin Pros • Callback function for extra control when animation is done. • Very backwards compatible 
 (IE6 support with jQuery 1.9 or earlier)
  62. Cons • Need to mix & match with JS events:

    • Might miss the animation on page load. • No CSS-only “transitionend” callback. • CSS keyframe animations can get hairy. • No IE9 support. Pros • No real CSS change from the JS version. • Automatically hardware accelerated. • CSS-only solution for :hover rollovers. R E C A P C S S 3 Tr a n s i t i o n s
  63. B ro w s e r s u p p

    o r t C S S 3 T R A N S I T I O N S http://caniuse.com/#feat=css-transitions
  64. Fe a t u r e d e t e

    c t i o n C S S 3 T R A N S I T I O N S For backwards compatibility, use Modernizr: JS 
 if  (Modernizr.csstransitions)  {
    $('.slider').css({left:targetX});
 }else{
    $('.slider').animate({left:targetX},  200);
 } CSS 
 .slider  {
    position:  relative;
    left:  0;
    transition:  left  200ms  
        cubic-­‐bezier(0.39,  0.575,  0.565,  1);
 }
 HTML 
 <div  class="slider">
    <ul><li>1</li><li>2<li>
    <li>3</li><ul>
 </div>
  65. TWITTER @PearlChen GOOGLE+ klab.ca/+ P E A R L C

    H E N T h a n k y o u ! 
 ( D e m o s : g i t h u b . c o m / p e a r l c h e n / a n g u l a r- d e m o s ) F I N