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

Going mobile with Angular

Ari
December 10, 2013

Going mobile with Angular

Talk at AngularJS Mountain View and San Francisco, 12/9 and 12/10

Ari

December 10, 2013
Tweet

More Decks by Ari

Other Decks in Programming

Transcript

  1. Ari Lerner Co-founder of Fullstack.io Author of ng-book, ng-newsletter.com, The

    Rails 4 Way, and Riding Rails on AngularJS Instructor at HackReactor Mentor at HackBright, Dev Bootcamp Background in systems architecture and distributed systems
  2. We need to consider: Getting that native app feeling Match

    well-trained user expectations Keep it speedy Make it beautiful
  3. < ! - - < h e a d >

    < / h e a d > < b o d y > - - > < ! - - i n l i n e s t y l e s h e r e - - > < d i v n g - a p p = " b d a y A p p " n g - c o n t r o l l e r = " F r a m e C t r l " > < ! - - S p l a s h s c r e e n - - > < d i v c l a s s = " s p l a s h " n g - c l o a k = " " > < p > L o a d i n g . . . < / p > < / d i v > < ! - - T h e r e s t o f t h e a p p - - > < / d i v >
  4. [ n g - c l o a k ]

    . s p l a s h { d i s p l a y : b l o c k ! i m p o r t a n t ; } [ n g - c l o a k ] { d i s p l a y : n o n e ; } . s p l a s h { b a c k g r o u n d - c o l o r : b l u e ; }
  5. < l i n k r e l = "

    s t y l e s h e e t " m e d i a = " s c r e e n a n d ( m a x - w i d t h : 9 7 9 p x ) " h r e f = " s t y l e s / m o b i l e . c s s " >
  6. < l i n k r e l = "

    s t y l e s h e e t " d a t a - m e d i a = " s c r e e n a n d ( m a x - w i d t h : 9 7 9 p x ) " d a t a - h r e f = " s t y l e s / m o b i l e . c s s " c l a s s = " m q " >
  7. f u n c t i o n m e

    d i a q u e r y l o a d ( ) { v a r m q s = d o c u m e n t . q u e r y S e l e c t o r A l l ( ' . m q ' ) , a l l = m q s . l e n g t h , c u r r = n u l l , a t t r = n u l l ; w h i l e ( a l l - - ) { c u r r = m q s [ a l l ] ; i f ( c u r r . d a t a s e t . m e d i a & & w i n d o w . m a t c h M e d i a ( c u r r . d a t a s e t . m e d i a ) . m a t c h e s ) { f o r ( a t t r i n c u r r . d a t a s e t ) { i f ( a t t r ! = = ' m e d i a ' ) { c u r r . s e t A t t r i b u t e ( a t t r , c u r r . d a t a s e t [ a t t r ] ) ; } } } } } m e d i a q u e r y l o a d ( ) ;
  8. < l i n k r e l = "

    s t y l e s h e e t " n g - i f = " t o u c h " h r e f = " s t y l e s / m o b i l e . c s s " >
  9. . p a g e { b a c k

    g r o u n d - i m a g e : u r l ( ' / i m a g e s / d u c k s . p n g ' ) ; } @ m e d i a ( m a x - w i d t h : 3 2 0 p x ) { . p a g e { b a c k g r o u n d - i m a g e : u r l ( ' / i m a g e / s m a l l d u c k s . p n g ' ) ; } }
  10. Minify Angular code Post minification a n g u l

    a r . m o d u l e ( ' m y A p p ' ) . c o n t r o l l e r ( ' H o m e C o n t r o l l e r ' , f u n c t i o n ( $ s c o p e ) { $ s c o p e . n a m e = ' A r i ' ; } ) ; a n g u l a r . m o d u l e ( " m y A p p " ) . c o n t r o l l e r ( " H o m e C o n t r o l l e r " , f u n c t i o n ( e ) { e . n a m e = " A r i " } )
  11. Solution: [ ] notation a n g u l a

    r . m o d u l e ( ' m y A p p ' ) . c o n t r o l l e r ( ' H o m e C o n t r o l l e r ' , [ ' $ 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 d e f i n i t i o n } ] )
  12. Use y e o m a n . i o

    when possible
  13. $ y o a n g u l a r

    $ g r u n t b u i l d
  14. Non-angular d o c u m e n t .

    o n r e a d y s t a t e c h a n g e = f u n c t i o n ( ) { i f ( d o c u m e n t . r e a d y S t a t e = = = ' c o m p l e t e ' ) { / / B r o w s e r l o a d e d } }
  15. Angular content a n g u l a r .

    m o d u l e ( ' m y A p p ' , [ ] ) . r u n ( f u n c t i o n ( ) { / / E x e c u t e p a g e f u n c t i o n s h e r e / / a s t h i s i s n o t i n t h e c r i t i c a l / / p a t h a n d i s l o a d e d / / a f t e r t h e D O M i s r e a d y } ) ;
  16. a n g u l a r . m o

    d u l e ( ' m y A p p ' ) . p r o v i d e r ( ' F B S e r v i c e ' , f u n c t i o n ( ) { f u n c t i o n c r e a t e S c r i p t ( $ d o c u m e n t , c a l l b a c k , s u c c e s s ) { v a r s c r i p t T a g = $ d o c u m e n t . c r e a t e E l e m e n t ( ' s c r i p t ' ) ; s c r i p t T a g . a s y n c = t r u e ; s c r i p t T a g . s r c = ' / / c o n n e c t . f a c e b o o k . n e t / e n _ U S / a l l . j s ' ; s c r i p t T a g . o n r e a d y s t a t e c h a n g e = f u n c t i o n ( ) { i f ( t h i s . r e a d y S t a t e = = ' c o m p l e t e ' ) { c a l l b a c k ( ) ; } } s c r i p t T a g . o n l o a d = c a l l b a c k ; $ d o c u m e n t . g e t E l e m e n t s B y T a g N a m e ( ' b o d y ' ) [ 0 ] . a p p e n d C h i l d ( s c r i p t T a g ) ; } t h i s . $ g e t = f u n c t i o n ( $ d o c u m e n t , $ t i m e o u t , $ q , $ w i n d o w ) { v a r d e f e r r e d = $ q . d e f e r ( ) ; c r e a t e S c r i p t ( $ d o c u m e n t [ 0 ] , f u n c t i o n ( c a l l b a c k ) { F B . i n i t ( { a p p I D : " 1 2 3 4 2 3 4 2 3 4 1 " } ) ; $ t i m e o u t ( f u n c t i o n ( ) { d e f e r r e d . r e s o l v e ( $ w i n d o w . F B ) ; } ) ; } ) ; r e t u r n d e f e r r e d . p r o m i s e ; } } ) ;
  17. a n g u l a r . m o

    d u l e ( ' m y A p p ' ) . f a c t o r y ( ' F a c e b o o k ' , f u n c t i o n ( $ q , F B S e r v i c e ) { r e t u r n { g e t U s e r P r o f i l e : f u n c t i o n ( ) { r e t u r n F B S e r v i c e . t h e n ( f u n c t i o n ( F B ) { F B . a p i ( ' / m e ' , f u n c t i o n ( u s e r ) { i f ( u s e r . e r r o r ) r e t u r n $ q . r e j e c t ( u s e r . e r r o r ) ; e l s e r e t u r n u s e r ; } ) } ) ; } } } ) ;
  18. < l i n k r e l = "

    s t y l e s h e e t " h r e f = " / m a i n . c s s " > < l i n k r e l = " s t y l e s h e e t " h r e f = " / m o b i l e . c s s " >
  19. Use l o c a l S t o r

    a g e for multiple sessions and offline use
  20. a n g u l a r . m o

    d u l e ( ' m y A p p ' ) . c o n t r o l l e r ( ' M a i n C o n t r o l l e r ' , f u n c t i o n ( F B ) { v a r c u r r O f f s e t = 0 ; v a r l s = l o c a l S t o r a g e . g e t I t e m ( ' f r i e n d s - ' + c u r r O f f s e t ) ; i f ( ! l s ) { u p d a t e F r i e n d s ( c u r r O f f s e t ) . t h e n ( f u n c t i o n ( f r i e n d s ) { $ s c o p e . f r i e n d s = f r i e n d s ; } ) ; } e l s e { $ s c o p e . f r i e n d s = J S O N . p a r s e ( l s ) ; } v a r u p d a t e F r i e n d s = f u n c t i o n ( o f f s e t ) { F B . g e t F r i e n d s ( { o f f s e t : o f f s e t } ) . t h e n ( f u n c t i o n ( f r i e n d s ) { l o c a l S t o r a g e . s e t I t e m ( ' f r i e n d s - ' + o f f s e t , J S O N . s t r i n g i f y ( o u t p u t ) ) ; } ) } } ) ;
  21. angular-cache < s c r i p t s r

    c = " b o w e r _ c o m p o n e n t s / a n g u l a r - c a c h e / d i s t / a n g u l a r - c a c h e . j s " > < / s c r i p t > a n g u l a r . m o d u l e ( ' m y A p p ' , [ ' j m d o b r y . a n g u l a r - c a c h e ' ] )
  22. a n g u l a r . s e

    r v i c e ( ' F B ' , f u n c t i o n ( $ a n g u l a r C a c h e F a c t o r y ) { v a r c a c h e = $ a n g u l a r C a c h e F a c t o r y ( ' f b C a c h e ' , { s t o r a g e M o d e : ' l o c a l S t o r a g e ' , d e l e t e O n E x p i r e : ' a g g r e s s i v e ' , m a x A g e : 6 0 0 0 0 , o n E x p i r e : f u n c t i o n ( k e y , v a l ) { F B . g e t F r i e n d s ( ) . t h e n ( f u n c t i o n ( f r i e n d s ) { / / r e f r e s h c a c h e . p u t ( k e y , f r i e n d s ) ; } ) } } ) ; } ) ;
  23. < m e t a n a m e =

    " v i e w p o r t " c o n t e n t = " w i d t h = d e v i c e - w i d t h , i n i t i a l - s c a l e = 1 . 0 , m a x i m u m - s c a l e = 1 . 0 , u s e r - s c a l a b l e = n o " >
  24. How to integrate with them? Custom JavaScript that's dependent upon

    jQuery and angular doesn't know about them
  25. a n g u l a r . m o

    d u l e ( ' a l T o u c h D e v i c e ' , [ ] ) . p r o v i d e r ( ' T o u c h D e v i c e ' , f u n c t i o n ( ) { v a r d e v i c e T y p e = f a l s e ; t h i s . s e t T o u c h D e v i c e = f u n c t i o n ( t ) { d e v i c e T y p e = t r u e ; } t h i s . $ g e t = f u n c t i o n ( ) { r e t u r n d e v i c e T y p e ; } } ) ;
  26. a n g u l a r . m o

    d u l e ( ' m y A p p ' ) . c o n f i g ( f u n c t i o n ( T o u c h D e v i c e P r o v i d e r ) { i f ( M o d e r n i z r . t o u c h ) T o u c h D e v i c e P r o v i d e r . s e t T o u c h D e v i c e ( ) ; } ) ;
  27. / / S a s s . l e f

    t { & . n g - e n t e r , & . n g - l e a v e { b a c k g r o u n d : i n h e r i t ; - w e b k i t - t r a n s i t i o n : . 5 5 s e a s e - i n - o u t ; } & . n g - e n t e r { z - i n d e x : 1 0 1 ; - w e b k i t - t r a n s f o r m : t r a n s l a t e X ( 1 0 0 % ) ; & . n g - e n t e r - a c t i v e { - w e b k i t - t r a n s f o r m : t r a n s l a t e X ( 0 ) ; } } & . n g - l e a v e { z - i n d e x : 1 0 0 ; - w e b k i t - t r a n s f o r m : t r a n s l a t e X ( 0 ) ; & . n g - l e a v e - a c t i v e { - w e b k i t - t r a n s f o r m : t r a n s l a t e X ( - 1 0 0 % ) ; } } }
  28. . r u n ( f u n c t

    i o n ( $ r o o t S c o p e , $ w i n d o w ) { $ r o o t S c o p e . a n i m a t i o n s . p a g e D i r e c t i o n = ' ' ; $ r o o t S c o p e . $ o n ( ' $ r o u t e C h a n g e S t a r t ' , f u n c t i o n ( e v t , n e x t , c u r r ) { i f ( c u r r & & n e x t ) { i f ( c u r r . d e p t h < n e x t . d e p t h ) $ r o o t S c o p e . a n i m a t i o n s . p a g e D i r e c t i o n = ' l e f t ' ; e l s e $ r o o t S c o p e . a n i m a t i o n s . p a g e D i r e c t i o n = ' r i g h t ' ; } } ) } )
  29. < d i v c l a s s =

    " c o n t e n t " > < d i v n g - c l a s s = " a n i m a t i o n . p a g e D i r e c t i o n " n g - v i e w = " " > < / d i v > < / d i v >
  30. ngTouch < s c r i p t s r

    c = " b o w e r _ c o m p o n e n t s / a n g u l a r - t o u c h / a n g u l a r - t o u c h . j s " > < / s c r i p t > a n g u l a r . m o d u l e ( ' m y A p p ' , [ ' n g T o u c h ' ] )
  31. < d i v n g - s w i

    p e - l e f t = " n e x t P a g e ( ) " n g - s w i p e - r i g h t = " p r e v P a g e ( ) " n g - c l a s s = " { ' s w i p e - a n i m a t i o n ' : t o u c h , ' s l i d e - l e f t ' : l o a d i n g = = = ' n e x t ' , ' s l i d e - r i g h t ' : l o a d i n g = = = ' p r e v ' } " > < / d i v >
  32. / / S a S S . s w i

    p e - a n i m a t i o n { & . n g - a n i m a t e . s l i d e - l e f t { a n i m a t i o n : s l i d e L e f t E n t e r 0 . 5 s ; - w e b k i t - a n i m a t i o n : s l i d e L e f t E n t e r 0 . 5 s ; } & . n g - a n i m a t e . s l i d e - l e f t . s l i d e - l e f t - r e m o v e { a n i m a t i o n : s l i d e L e f t L e a v e 0 . 5 s ; - w e b k i t - a n i m a t i o n : s l i d e L e f t L e a v e 0 . 5 s ; } }
  33. < s p a n > { { f r

    i e n d . b i r t h d a y | d a t e : ' M M M M d d ' } } < / s p a n >
  34. a n g u l a r . m o

    d u l e ( ' m y A p p ' ) . c o n t r o l l e r ( ' M a i n C o n t r o l l e r ' , f u n c t i o n ( $ s c o p e , $ f i l t e r ) { v a r u p d a t e F r i e n d s = f u n c t i o n ( ) { F B . g e t F r i e n d s ( ) . t h e n ( f u n c t i o n ( f r i e n d s ) { v a r a r r = [ ] ; a n g u l a r . f o r E a c h ( f r i e n d s , f u n c t i o n ( v a l u e , k e y ) { i f ( v a l u e . b i r t h d a y ) { v a l u e [ ' f o r m a t t e d _ b i r t h d a y ' ] = $ f i l t e r ( ' d a t e ' ) ( v a l u e [ ' b i r t h d a y ' ] , ' M M M M d d ' ) a r r . p u s h ( v a l u e ) ; } } ) ; $ s c o p e . f r i e n d s = $ f i l t e r ( ' o r d e r B y ' ) ( a r r , ' b i r t h d a y ' ) ; } ) } } ) ;
  35. < s c r i p t s r c

    = " b o w e r _ c o m p o n e n t s / a n g u l a r - b i n d o n c e / b i n d o n c e . j s " > < / s c r i p t > a n g u l a r . m o d u l e ( ' m y A p p ' , [ ' p a s v a z . b i n d o n c e ' ] ) ;
  36. < u l c l a s s = "

    l i s t l i s t - g r o u p " > < d i v c l a s s = " s p i n n e r " > < / d i v > < l i b i n d o n c e = " " c l a s s = " t i l e - p h o t o l i s t - g r o u p - i t e m " n g - r e p e a t = " f r i e n d i n f r i e n d s t r a c k b y f r i e n d . i d " > < a b o - h r e f = " ' # / s h a r e / ' + f r i e n d . i d " > < i m g b o - s r c = " ' h t t p s : / / g r a p h . f a c e b o o k . c o m / ' + f r i e n d . i d + ' / p i c t u r e ' " > < d i v c l a s s = " d e t a i l s " > < h 3 b o - t e x t = " f r i e n d . n a m e " > < / h 3 > < s m a l l b o - t e x t = " f r i e n d . f o r m a t t e d _ b i r t h d a y " > < / s m a l l > < / d i v > < s p a n c l a s s = " c h e v r o n " > < / s p a n > < / a > < / l i > < / u l >
  37. v a r u p d a t e F

    r i e n d s = f u n c t i o n ( ) { F B . g e t F r i e n d s ( { l i m i t : l i m i t , o f f s e t : o f f s e t } ) . t h e n ( f u n c t i o n ( f r i e n d s ) { / / . . . } ) } u p d a t e F r i e n d s ( ) ;
  38. $ s c o p e . n e x

    t P a g e = f u n c t i o n ( ) { o f f s e t + = l i m i t ; u p d a t e F r i e n d s ( ) ; } $ s c o p e . p r e v P a g e = f u n c t i o n ( ) { o f f s e t - = l i m i t ; u p d a t e F r i e n d s ( ) ; }
  39. Slow click By default, mobile browsers implement about a 300ms

    delay between touches and firing an event
  40. ngTouch It only rewrites n g - c l i

    c k and is a bit buggy...
  41. Use FastClick < s c r i p t s

    r c = " b o w e r _ c o m p o n e n t s / f a s t c l i c k / l i b / f a s t c l i c k . j s " > < / s c r i p t > a n g u l a r . m o d u l e ( ' m y A p p ' ) . r u n ( f u n c t i o n ( ) { F a s t C l i c k . a t t a c h ( d o c u m e n t . b o d y ) ; } )
  42. a n g u l a r . m o

    d u l e ( ' m y A p p . s e r v i c e s ' ) . f a c t o r y ( ' N e t w o r k B a t c h e r ' , f u n c t i o n ( $ h t t p ) { v a r s e r v i c e = { p r o m i s e s : [ ] , a d d C a l l : f u n c t i o n ( o b j ) { v a r p r o m i s e = $ h t t p ( o b j ) ; s e r v i c e . p r o m i s e s . p u s h ( p r o m i s e ) ; r e t u r n p r o m i s e ; } , r u n A l l : f u n c t i o n ( ) { r e t u r n $ q . a l l ( s e r v i c e . p r o m i s e s ) ; } } r e t u r n s e r v i c e ; } )
  43. a n g u l a r . m o

    d u l e ( ' m y A p p . s e r v i c e s ' ) . f a c t o r y ( ' A c c o u n t ' , f u n c t i o n ( N e t w o r k B a t c h e r ) { r e t u r n { g e t A c c o u n t s : f u n c t i o n ( ) { r e t u r n N e t w o r k B a t c h e r . a d d C a l l ( { m e t h o d : ' G E T ' , u r l : ' / v 1 / a c c o u n t s . j s o n ' } ) } } } ) ;
  44. Preload templates # C a c h e a n

    d p r e l o a d t e m p l a t e s $ n p m i n s t a l l - - s a v e - d e v n g t e m p l a t e s $ g r u n t n g t e m p l a t e s