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 full-size slide

  2. Michał Miszczyszyn
    JavaScript developer at The Comet Cult

    @mmiszy

    [email protected]

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  5. AngularJS caveats

    View full-size 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 full-size slide

  7. 1. project structure

    View full-size slide

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

    View full-size 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 full-size slide

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

    View full-size 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 full-size slide

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

    View full-size slide

  13. 2. jQuery and jqLite

    View full-size slide

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

    View full-size 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 full-size slide

  16. 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 full-size slide

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

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

    View full-size slide

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

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

    View full-size slide

  19. 3. interacting with ng

    View full-size slide

  20. 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 full-size slide

  21. 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 full-size slide

  22. 4. global services

    View full-size slide

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

    View full-size slide

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

    _.partition(…);

    });
    • but it's wrong!

    View full-size slide

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

    View full-size slide

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

    _.partition()

    });

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

    return $window._;

    });

    View full-size slide

  27. 5. service vs factory

    View full-size slide

  28. 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 full-size slide

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

    View full-size slide

  30. 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 full-size slide

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

    }

    });

    View full-size slide

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

    });

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  35. $scope
    {{myVar}}




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

    View full-size slide

  36. $scope
    {{myVar}}




    • …this still works…

    View full-size slide

  37. $scope
    {{myVar}}




    • …and this doesn't!

    View full-size slide

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

    View full-size slide

  39. $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 full-size slide

  40. $scope
    {{a.b}}





    $scope.a = {};

    View full-size slide

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


    View full-size slide

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

    View full-size slide

  43. $scope
    • controller as syntax


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

    View full-size slide

  44. $scope
    {{myCtrl.myVar}}




    View full-size slide

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

    this.isVisible = true;

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

    View full-size slide

  46. 7. dependency injection

    View full-size slide

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

    View full-size slide

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

    // $timeout is injected!

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

    View full-size slide

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

    View full-size slide

  50. COULD YOU NOT?

    View full-size slide

  51. 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 full-size slide

  52. 8. communication

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  56. 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 full-size slide

  57. 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 full-size slide

  58. 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 full-size slide

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

    View full-size slide

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

    this.getUser = function () { … };

    this.storeUser = function () { … };

    });

    View full-size slide

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

    View full-size slide

  62. communication
    AuthStore.addObserver(doSomething);

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

    View full-size slide

  63. 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 full-size slide

  64. Michał Miszczyszyn
    JavaScript developer at The Comet Cult

    @mmiszy

    [email protected]

    View full-size slide

  65. AngularJS caveats

    View full-size slide