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

Everything You Always Wanted to Know About AngularJS But Were Afraid to Ask

Everything You Always Wanted to Know About AngularJS But Were Afraid to Ask

About top AngularJS caveats and bad practises.

This presentation was given during meet.js Szczecin on 10th March, 2015.

Michał Miszczyszyn

March 10, 2015
Tweet

More Decks by Michał Miszczyszyn

Other Decks in Programming

Transcript

  1. Everything You Always Wanted
    to Know About AngularJS
    But Were Afraid to Ask

    View Slide

  2. Michał Miszczyszyn
    JavaScript developer at The Comet Cult

    @mmiszy

    [email protected]

    View Slide

  3. Today’s presentation:
    • Top AngularJS caveats
    • Fixes to those caveats
    • … that's it!

    View Slide

  4. ca·ve·at
    an explanation or warning that should be
    remembered when you are doing or
    thinking about something

    View Slide

  5. AngularJS caveats

    View Slide

  6. AngularJS caveats
    1. project structure
    2. jQuery and jqLite
    3. interacting with ng
    4. global services
    5. service vs factory
    6. $scope
    7. dependency injection
    8. communication

    View Slide

  7. 1. project structure

    View Slide

  8. project structure
    • at the beginning – no recommended
    project structure
    • by default apps were divided into:
    controllers, services,
    directives…

    View Slide

  9. project structure
    • it's perfectly fine for small applications
    • The caveat: it doesn't work for larger apps
    • a blog post from February 2014 changed it:
    • https://blog.angularjs.org/2014/02/an-
    angularjs-style-guide-and-best.html

    View Slide

  10. project structure
    e2e-tests/
    sampleapp/
    app.css
    app.js
    app-controller.js
    app-controller_test.js
    index.html
    components/ …

    View Slide

  11. project structure
    components/
    payments/
    payments.js // module routing
    payments.html
    payments-controller.js
    payments-service.js
    payments-service_test.js
    payments.css

    View Slide

  12. project structure
    • this approach is much cleaner
    • easier to find files
    • more flexible

    View Slide

  13. 2. jQuery and jqLite

    View Slide

  14. jQuery and jqLite
    • $ is undefined?
    • Error: Looking up elements via
    selectors is not supported by jqLite!
    • (even with jQuery included*)

    View Slide

  15. jQuery and jqLite
    • The caveat: jqLite is not jQuery
    • jqLite provides a limited set of
    functionalities from jQuery
    • if you want to use jQuery, include it
    before angular.js file

    View Slide

  16. View Slide

  17. jQuery and jqLite
    • The caveat: jqLite is not jQuery
    • jqLite provides a limited set of
    functionalities from jQuery
    • if you want to use jQuery, include it
    before angular.js file

    View Slide

  18. jQuery and jqLite
    • angular.js before jquery.js:
    $('#home')//ok

    angular.element('#home')//nope

    View Slide

  19. jQuery and jqLite
    • angular.js after jquery.js:
    $('#home')//ok

    angular.element('#home')//ok
    • all elements wrapped in jQuery

    View Slide

  20. 3. interacting with ng

    View Slide

  21. interacting with ng
    • Angular makes a lot of things easier
    • (duh)
    • The caveat: for anything to work with
    Angular it has to be done

    The Angular Way®

    View Slide

  22. interacting with ng
    • many people ask why this won't work
    $('input')
    .attr('ng-model', 'name');
    • you shouldn't try to interact with Angular
    from the outside
    • use directives instead

    View Slide

  23. 4. global services

    View Slide

  24. global services
    • you can use any other libraries with
    Angular
    • The caveat: You should wrap them in
    angular service

    View Slide

  25. global services
    • eg. Underscore
    • you can simply access it in your controllers:
    app.controller('Ctrl', function(){

    _.partition(…);

    });
    • but it's wrong!

    View Slide

  26. global services
    • much harder to write unit tests
    • impossible to change the
    implementation
    • you want to use DI for this

    View Slide

  27. global services
    app.controller('Ctrl',function(_){

    _.partition()

    });

    app.factory('_',function($window){

    return $window._;

    });

    View Slide

  28. 5. service vs factory

    View Slide

  29. service vs factory
    • angular brings a lot of new concepts
    • one of them are services, factories
    and providers
    • the caveat: many people find it hard to
    understand how to use them

    View Slide

  30. View Slide

  31. service vs factory
    • factory expects a function as an
    argument
    • service expects a constructor
    • provider is more complicated
    • all return singletons

    View Slide

  32. service vs factory
    app.factory('a', fna);

    app.service('b', fnb);

    app.provider('c', fnc);

    a = fna();
    b = new fnb();
    c = (new fnc()).$get();

    View Slide

  33. service vs factory
    app.factory('myFactory', function() {
    return {
    sayHello: function(name) {
    return "Hello world " + name;
    }

    }

    });

    View Slide

  34. service vs factory
    app.service('myService', function() {
    this.sayHello = function(name) {
    return "Hello world " + name;
    };

    });

    View Slide

  35. service vs factory
    • usually all you need is just a service

    View Slide

  36. 6. $scope

    View Slide

  37. $scope
    • The caveat: everything
    • a "mystical" object
    • there's a lot of confusion about it
    • quick example

    View Slide

  38. $scope
    {{myVar}}




    • if you type in the input, the text shows
    above

    View Slide

  39. $scope
    {{myVar}}




    • …this still works…

    View Slide

  40. $scope
    {{myVar}}




    • …and this doesn't!

    View Slide

  41. View Slide

  42. $scope
    • ng-if creates a child scope
    • ng-show doesn't
    • it's not intuitive at all!

    View Slide

  43. $scope
    • authors of Angular used to advice:
    • ”if you use ng-model there has to be
    a dot somewhere. If you don't have
    a dot, you're doing it wrong”

    View Slide

  44. $scope
    {{a.b}}





    $scope.a = {};

    View Slide

  45. $scope
    • more generic solution
    • property on the scope:
    $scope.MyCtrl = $scope;


    View Slide

  46. $scope
    • this solution is ugly and there's still
    room for bugs
    • …so what's $scope even for?
    • ?
    • we can do without it!

    View Slide

  47. $scope
    • controller as syntax


    • local name for controller object
    • let's fix the previous example!

    View Slide

  48. $scope
    {{myCtrl.myVar}}




    View Slide

  49. $scope
    app.controller('MyCtrl',
    function() {

    this.isVisible = true;

    });
    • no more $scope!
    • use this – feels more like JavaScript

    View Slide

  50. 7. dependency injection

    View Slide

  51. dependency injection
    • one of the best things in Angular
    • cleaner code
    • easier to test

    View Slide

  52. dependency injection
    app.controller('MyCtrl',
    function($timeout) {

    // $timeout is injected!

    });
    • very simple to use
    • angular can inject based on argument name

    View Slide

  53. dependency injection
    • The caveat: minification
    app.controller("MyCtrl",function(a){});
    • Unknown provider: aProvider

    View Slide

  54. COULD YOU NOT?

    View Slide

  55. dependency injection
    • there are different solutions:
    • not to minify parts of files
    • use array notation:
    ["$timeout",function($timeout){}]
    • use ng-annotate – does this automatically

    View Slide

  56. 8. communication

    View Slide

  57. communication
    • often in the application you need to
    communicate between components
    • the caveat: Angular doesn't provide
    good means to do that

    View Slide

  58. communication
    • there are a few builtin solutions:
    • $broadcast
    • $rootScope
    • $watch

    View Slide

  59. communication
    • Which should be used to
    communicate between controllers?
    • None.

    View Slide

  60. View Slide

  61. communication
    • $brodcast – often abused
    • $broadcast('myCtrl:sth') – don't!
    • use only for events that are relevant to the
    whole application
    • login, closing the app etc…

    View Slide

  62. communication
    • $rootScope – often abused…
    • $rootScope.sth = 123 – don't!
    • it's as bad as global variables
    • use for configuration settings or things
    like page title

    View Slide

  63. communication
    • $watch – often abused…
    • $watch(() => { MyService; }, …)
    • the rule of thumb: limit its usage to a minimum
    • makes testing much harder
    • might be bad for performance

    View Slide

  64. communication
    • good solution: use a shared service
    • straighforward to use to just share
    data between controllers
    • simply store the data or functions

    View Slide

  65. communication
    app.service('AuthStore', function (){

    this.getUser = function () { … };

    this.storeUser = function () { … };

    });

    View Slide

  66. communication
    • good solution: observer pattern
    • well known
    • easy to implement
    • no performance hit
    • good for observing changes in the data

    View Slide

  67. communication
    AuthStore.addObserver(doSomething);

    $scope.$on('$destroy', function () {
    AuthStore.removeObserver(doSomething);
    });

    View Slide

  68. Sources:
    • http://stackoverflow.com/questions/20369514/building-a-web-app-in-angularjs-without-jquery
    • https://www.airpair.com/angularjs/posts/top-10-mistakes-angularjs-developers-make
    • http://www.bennadel.com/blog/2752-using-jquery-instead-of-jqlite-in-angularjs.htm
    • https://blog.angularjs.org/2014/02/an-angularjs-style-guide-and-best.html
    • https://docs.google.com/document/d/1XXMvReO8-
    Awi1EZXAXS4PzDzdNvV6pGcuaF4Q9821Es/pub
    • http://toddmotto.com/digging-into-angulars-controller-as-syntax/
    • http://stackoverflow.com/questions/12008908/how-can-i-pass-variables-between-controllers
    • http://stackoverflow.com/questions/13762228/confused-about-service-vs-factory/
    13763886#13763886
    • http://giphy.com/search/looney-tunes/5

    View Slide

  69. Michał Miszczyszyn
    JavaScript developer at The Comet Cult

    @mmiszy

    [email protected]

    View Slide

  70. AngularJS caveats

    View Slide

  71. Thank you!

    View Slide

  72. Questions?

    View Slide