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

AngularJS in one day

AngularJS in one day

Slides at a half-day workshop I gave at Google, San Francisco.

Todd Motto

October 27, 2013
Tweet

More Decks by Todd Motto

Other Decks in Programming

Transcript

  1. SETUP ESSENTIALS (HTML) < d i v n g -

    a p p = " m y A p p " > < d i v n g - c o n t r o l l e r = " M a i n C t r l " > < ! - - c o n t r o l l e r l o g i c - - > < / d i v > < / d i v >
  2. SETUP ESSENTIALS (JAVASCRIPT) v a r m y A p

    p = a n g u l a r . m o d u l e ( ' m y A p p ' , [ ] ) ; m y A p p . c o n t r o l l e r ( ' M a i n C t r l ' , [ ' $ s c o p e ' , f u n c t i o n ( $ s c o p e ) { / / C o n t r o l l e r l o g i c } ] ) ;
  3. CONTROLLERS: PUSHING TO THE $SCOPE (HTML) < d i v

    n g - a p p = " m y A p p " > < d i v n g - c o n t r o l l e r = " M a i n C t r l " > { { t e x t } } < / d i v > < / d i v >
  4. CONTROLLERS: PUSHING TO THE $SCOPE (JAVASCRIPT) v a r m

    y A p p = a n g u l a r . m o d u l e ( ' m y A p p ' , [ ] ) ; m y A p p . c o n t r o l l e r ( ' M a i n C t r l ' , [ ' $ s c o p e ' , f u n c t i o n ( $ s c o p e ) { $ s c o p e . t e x t = ' H e l l o , A n g u l a r f a n a t i c . ' ; } ] ) ;
  5. CONTROLLERS: PUSHING TO THE $SCOPE (OUTPUT) < d i v

    n g - a p p = " m y A p p " > < d i v n g - c o n t r o l l e r = " M a i n C t r l " > H e l l o , A n g u l a r f a n a t i c . < / d i v > < / d i v >
  6. DIRECTIVES: MANIPULATING THE DOM Reusable chunks of code injected Packaged

    and managed individually Custom buttons, forms, tooltips (components)
  7. DIRECTIVES: DOM DECLARATIONS < ! - - 1 : a

    s a n a t t r i b u t e d e c l a r a t i o n - - > < a c u s t o m - b u t t o n > C l i c k m e < / a > < ! - - 2 : a s a c u s t o m e l e m e n t - - > < c u s t o m - b u t t o n > C l i c k m e < / c u s t o m - b u t t o n > < ! - - 3 : a s a c l a s s ( u s e d f o r o l d I E c o m p a t ) - - > < a c l a s s = " c u s t o m - b u t t o n " > C l i c k m e < / a > < ! - - 4 : a s a c o m m e n t - - > < ! - - d i r e c t i v e : c u s t o m - b u t t o n - - >
  8. DIRECTIVES: JAVASCRIPT SETUP m y A p p . d

    i r e c t i v e ( ' c u s t o m B u t t o n ' , f u n c t i o n ( ) { r e t u r n { r e s t r i c t : ' A ' , r e p l a c e : t r u e , t r a n s c l u d e : t r u e , t e m p l a t e : ' < a h r e f = " " c l a s s = " c - b u t t o n " n g - t r a n s c l u d e > ' + ' < i c l a s s = " i c o n - o k - s i g n " > < / i > ' + ' < / a > ' , l i n k : f u n c t i o n ( s c o p e , e l e m e n t , a t t r s ) { / / D O M m a n i p u l a t i o n / e v e n t s h e r e ! } } ; } ) ;
  9. DIRECTIVES: DEFINITIONS restrict: usage, Attribute/Element/etc. replace: replaces declarative node transclude:

    Inject existing DOM (text) inside template: Markup, either <script> or ext .html file link: Events, custom manipulation
  10. SERVICES: STATIC USE CASE m y A p p .

    s e r v i c e ( ' M a t h ' , f u n c t i o n ( ) { t h i s . m u l t i p l y = f u n c t i o n ( x , y ) { r e t u r n x * y ; } ; } ) ;
  11. FACTORY: MODEL ABSTRACTION m y A p p . f

    a c t o r y ( ' J S O N F a c t o r y ' , [ ' $ h t t p ' , f u n c t i o n ( $ h t t p ) { v a r J S O N F a c t o r y = { g e t U s e r s : f u n c t i o n ( c a l l b a c k ) { $ h t t p . g e t ( ' / u s e r s ' ) . s u c c e s s ( c a l l b a c k ) ; } , p o s t U s e r s : f u n c t i o n ( c a l l b a c k ) { $ h t t p . p o s t ( ' / u s e r s U p d a t e ' ) . s u c c e s s ( c a l l b a c k ) ; } } ; r e t u r n J S O N F a c t o r y ; } ] ) ;
  12. FACTORY: DRY USAGE (EVERYWHERE!) / / d e p e

    n d e n c y i n j e c t m y A p p . c o n t r o l l e r ( ' M a i n C t r l ' , f u n c t i o n ( $ s c o p e , J S O N F a c t o r y ) { J S O N F a c t o r y . g e t U s e r s ( f u n c t i o n ( d a t a ) { $ s c o p e . u s e r s = d a t a ; / / o b j } ) ; } ] ) ;
  13. FILTERS: MANAGING YOUR DATA m y A p p .

    f i l t e r ( ' r e v e r s e ' , f u n c t i o n ( ) { r e t u r n f u n c t i o n ( i n p u t ) { v a r o u t = ' ' ; f o r ( v a r i = 0 ; i < i n p u t . l e n g t h ; i + + ) { o u t = i n p u t . c h a r A t ( i ) + o u t ; } r e t u r n o u t ; } } ) ;
  14. FILTERS: $SCOPE AS USUAL m y A p p .

    c o n t r o l l e r ( ' M a i n C t r l ' , [ ' $ s c o p e ' , f u n c t i o n ( $ s c o p e ) { $ s c o p e . g r e e t i n g = ' T o d d M o t t o ' ; } ] ) ;
  15. FILTERS: DECLARE (SINGLE, NO LOOP) < d i v n

    g - a p p = " m y A p p " > < d i v n g - c o n t r o l l e r = " M a i n C t r l " > < p > N o f i l t e r : { { g r e e t i n g } } < / p > < p > R e v e r s e : { { g r e e t i n g | r e v e r s e } } < / p > < / d i v > < / d i v >
  16. FILTERS: DECLARE (REPEAT, LOOP) < d i v n g

    - a p p = " m y A p p " > < u l n g - c o n t r o l l e r = " M a i n C t r l " > < l i n g - r e p e a t = " g r e e t i n g r e e t i n g s " > { { g r e e t | r e v e r s e } } < / l i > < / u l > < / d i v >
  17. CREATING YOUR FIRST APP Design: JSON design for best response

    Distribute: Integrate data w/Factory + Controllers Declare: Push to the $scope
  18. APP: DESIGN Design w/static data then replicate with backend endpoints

    / / i d e a l j s o n r e s p o n s e f r o m $ h t t p . g e t ( ) [ { " f r o m " : " S t e v e J o b s " , " s u b j e c t " : " I t h i n k I ' m h o l d i n g m y p h o n e w r o n g : / " , " s e n t " : " 2 0 1 3 - 1 0 - 0 1 T 0 8 : 0 5 : 5 9 Z " } , { " f r o m " : " E l l i e G o u l d i n g " , " s u b j e c t " : " I ' v e g o t S t a r r y E y e s , l u l z " , " s e n t " : " 2 0 1 3 - 0 9 - 2 1 T 1 9 : 4 5 : 0 0 Z " } , { " f r o m " : " M i c h a e l S t i p e " , " s u b j e c t " : " E v e r y b o d y h u r t s , s o m e t i m e s . " , " s e n t " : " 2 0 1 3 - 0 9 - 1 2 T 1 1 : 3 8 : 3 0 Z " } , { " f r o m " : " J e r e m y C l a r k s o n " , " s u b j e c t " : " T h i n k I ' v e f o u n d t h e b e s t c a r . . . I n t h e w o r l d " , " s e n t " : " 2 0 1 3 - 0 9 - 0 3 T 1 3 : 1 5 : 1 1 Z "
  19. APP: DISTRIBUTE (FACTORY CREATION) m y A p p .

    f a c t o r y ( ' J S O N F a c t o r y ' , [ ' $ h t t p ' , f u n c t i o n ( $ h t t p ) { v a r J S O N F a c t o r y = { g e t E m a i l s : f u n c t i o n ( c a l l b a c k ) { $ h t t p . g e t ( ' / u s e r s ' ) . s u c c e s s ( c a l l b a c k ) ; } , p o s t E m a i l C h a n g e s : f u n c t i o n ( c a l l b a c k ) { $ h t t p . p o s t ( ' / e m a i l U p d a t e s ' ) . s u c c e s s ( c a l l b a c k ) ; } } ; r e t u r n J S O N F a c t o r y ; } ] ) ;
  20. APP: DISTRIBUTE (CONTROLLER INJECTION) m y A p p .

    c o n t r o l l e r ( ' E m a i l C t r l ' , f u n c t i o n ( $ s c o p e , J S O N F a c t o r y ) { $ s c o p e . e m a i l s = { } ; / / n a m e s p a c e f o r d o m c l a r i t y J S O N F a c t o r y . g e t E m a i l s ( f u n c t i o n ( d a t a ) { $ s c o p e . e m a i l s . m e s s a g e s = d a t a ; / / r i d e o f f n / s } ) ; } ] ) ;
  21. APP: DECLARE < d i v n g - a

    p p = " m y A p p " > < u l n g - c o n t r o l l e r = " M a i n C t r l " > < l i n g - r e p e a t = " m e s s a g e i n e m a i l s . m e s s a g e " > F r o m : { { m e s s a g e . f r o m } } S u b j e c t : { { m e s s a g e . s u b j e c t } } { { m e s s a g e . s e n t | d a t e : ' M M M d , y h : m m : s s a ' } } < / l i > < / u l > < / d i v >
  22. CORE: NG-CLICK Scoped inline functions with access to elems, index,

    more < a n g - c l i c k = " d e l e t e E m a i l ( $ i n d e x ) " > D e l e t e e m a i l < / a >
  23. CORE: NG-MODEL Instantly reflected in the View + Model <

    i n p u t n g - m o d e l = " s e a r c h T e x t " >
  24. CORE: NG-SUBMIT Ajax form handling < f o r m

    n g - s u b m i t = " d o A w e s o m e A j a x ( ) ; " > < / f o r m >
  25. CORE: NG-DISABLED Form elements validation < b u t t

    o n t y p e = " s u b m i t " n g - d i s a b l e d = " ! c o n d i t i o n " > < / b u t t o n >
  26. CORE: NG-SHOW Also an ng-hide, both used depending on conditional

    state < a h r e f = " " n g - c l i c k = " t o g g l e = ! t o g g l e " > T o g g l e n a v < / a > < u l n g - s h o w = " t o g g l e " > < l i > L i n k 1 < / l i > < l i > L i n k 2 < / l i > < l i > L i n k 3 < / l i > < / u l >
  27. EXPRESSIONS: 'LENGTH' COMPARISONS, 'AND', 'OR' < h 3 > {

    { e m a i l s . m e s s a g e s & & ' E m a i l s ' | | ' N o e m a i l s ' } } < p n g - s h o w = " e m a i l s . m e s s a g e s . l e n g t h > 0 " > { { e m a i l s . m e s s a g e s . l e n g t h } } < / p > < / h 3 > < u l > < l i n g - r e p e a t = " m e s s a g e i n e m a i l s . m e s s a g e s " > < / l i > < / u l >
  28. ROUTING: DYNAMIC VIEW CONFIG m y A p p .

    c o n f i g ( [ ' $ r o u t e P r o v i d e r ' , f u n c t i o n ( $ r o u t e P r o v i d e r ) { $ r o u t e P r o v i d e r . w h e n ( ' / ' , { t e m p l a t e U r l : ' v i e w s / m a i n . h t m l ' } ) . w h e n ( ' / c a r t / i t e m : i d ' , { t e m p l a t e U r l : ' v i e w s / c a r t - i t e m . h t m l ' } ) . o t h e r w i s e ( { r e d i r e c t T o : ' / ' } ) ; } ] ) ;
  29. SERVER-SIDE: INSTANT JSON Perf benefits, no $http onload < !

    - - i n s i d e i n d e x . h t m l ( b o t t o m o f p a g e o f c ) - - > < s c r i p t > < / s c r i p t > w i n d o w . g l o b a l D a t a = { } ; g l o b a l D a t a . e m a i l s = < j a v a T a g H e r e T o G e n e r a t e M e s s a g e s > ;
  30. SERVER-SIDE: ANGULAR REFERENCE m y A p p . c

    o n t r o l l e r ( ' E m a i l s C t r l ' , f u n c t i o n ( $ s c o p e ) { $ s c o p e . e m a i l s = { } ; $ s c o p e . e m a i l s . m e s s a g e s = g l o b a l D a t a . e m a i l s ; } ] ) ;
  31. DEPENDENCY INJECTION Tell the app what APIs you want, Angular

    only grabs things it needs Minification
  32. DI: BEFORE MINIFICATION m y A p p . c

    o n t r o l l e r ( ' M a i n C t r l ' , [ ' $ s c o p e ' , ' D e p e n d e n c y ' , ' S e r v i c e ' , ' F a c t o r y ' , / / a r r a y f u n c t i o n ( $ s c o p e , D e p e n d e n c y , S e r v i c e , F a c t o r y ) { / / c o d e } ] ) ;
  33. DI: AFTER MINIFICATION m y A p p . c

    o n t r o l l e r ( ' M a i n C t r l ' , [ ' $ s c o p e ' , ' D e p e n d e n c y ' , ' S e r v i c e ' , ' F a c t o r y ' , / / k e e p s r e f e r e n c e f u n c t i o n ( a , b , c , d ) { / / a = $ s c o p e / / b = D e p e n d e n c y / / c = S e r v i c e / / d = F a c t o r y } ] ) ;
  34. THINKING ANGULAR (NG-THINKING) Scopes and data, not DOM, no add/remove/toggle

    classes, ever. Angular does this all for you based on data Let the data do the work, keep code as minimal as possible Abstract, abstract, abstract. Keep abstracting into different files for better management and copying individual files into new projects, premade working code