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.

8f7e1a0e97a69d5f7be4885c867b74ba?s=128

Michał Miszczyszyn

March 10, 2015
Tweet

Transcript

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

    Afraid to Ask
  2. Michał Miszczyszyn JavaScript developer at The Comet Cult
 @mmiszy
 michal@miszczyszyn.com

  3. Today’s presentation: • Top AngularJS caveats • Fixes to those

    caveats • … that's it!
  4. ca·ve·at an explanation or warning that should be remembered when

    you are doing or thinking about something
  5. AngularJS caveats

  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
  7. 1. project structure

  8. project structure • at the beginning – no recommended project

    structure • by default apps were divided into: controllers, services, directives…
  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
  10. project structure e2e-tests/ sampleapp/ app.css app.js app-controller.js app-controller_test.js index.html components/

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

    payments-service.js payments-service_test.js payments.css
  12. project structure • this approach is much cleaner • easier

    to find files • more flexible
  13. 2. jQuery and jqLite

  14. jQuery and jqLite • $ is undefined? • Error: Looking

    up elements via selectors is not supported by jqLite! • (even with jQuery included*)
  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
  16. None
  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
  18. jQuery and jqLite • angular.js before jquery.js: $('#home')//ok
 angular.element('#home')//nope

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

    all elements wrapped in jQuery
  20. 3. interacting with ng

  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®
  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
  23. 4. global services

  24. global services • you can use any other libraries with

    Angular • The caveat: You should wrap them in angular service
  25. global services • eg. Underscore • you can simply access

    it in your controllers: app.controller('Ctrl', function(){
 _.partition(…);
 }); • but it's wrong!
  26. global services • much harder to write unit tests •

    impossible to change the implementation • you want to use DI for this
  27. global services app.controller('Ctrl',function(_){
 _.partition()
 });
 app.factory('_',function($window){
 return $window._;
 });

  28. 5. service vs factory

  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
  30. None
  31. service vs factory • factory expects a function as an

    argument • service expects a constructor • provider is more complicated • all return singletons
  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();
  33. service vs factory app.factory('myFactory', function() { return { sayHello: function(name)

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

    return "Hello world " + name; };
 });
  35. service vs factory • usually all you need is just

    a service
  36. 6. $scope

  37. $scope • The caveat: everything • a "mystical" object •

    there's a lot of confusion about it • quick example
  38. $scope {{myVar}}
 <div>
 <input ng-model="myVar">
 </div> • if you type

    in the input, the text shows above
  39. $scope {{myVar}}
 <div ng-show="isVisible">
 <input ng-model="myVar">
 </div> • …this still

    works…
  40. $scope {{myVar}}
 <div ng-if="isVisible">
 <input ng-model="myVar">
 </div> • …and this

    doesn't!
  41. None
  42. $scope • ng-if creates a child scope • ng-show doesn't

    • it's not intuitive at all!
  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”
  44. $scope {{a.b}}
 <div ng-if="isVisible">
 <input ng-model="a.b">
 </div> 
 $scope.a =

    {};
  45. $scope • more generic solution • property on the scope:

    $scope.MyCtrl = $scope;
 <input ng-model="MyCtrl.x">
  46. $scope • this solution is ugly and there's still room

    for bugs • …so what's $scope even for? • ? • we can do without it!
  47. $scope • controller as syntax <div ng-controller="MyCtrl"> <div ng-controller="MyCtrl as

    myCtrl"> • local name for controller object • let's fix the previous example!
  48. $scope {{myCtrl.myVar}}
 <div ng-if="myCtrl.isVisible">
 <input ng-model="myCtrl.myVar">
 </div>

  49. $scope app.controller('MyCtrl', function() {
 this.isVisible = true;
 }); • no

    more $scope! • use this – feels more like JavaScript
  50. 7. dependency injection

  51. dependency injection • one of the best things in Angular

    • cleaner code • easier to test
  52. dependency injection app.controller('MyCtrl', function($timeout) {
 // $timeout is injected!
 });

    • very simple to use • angular can inject based on argument name
  53. dependency injection • The caveat: minification app.controller("MyCtrl",function(a){}); • Unknown provider:

    aProvider
  54. COULD YOU NOT?

  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
  56. 8. communication

  57. communication • often in the application you need to communicate

    between components • the caveat: Angular doesn't provide good means to do that
  58. communication • there are a few builtin solutions: • $broadcast

    • $rootScope • $watch
  59. communication • Which should be used to communicate between controllers?

    • None.
  60. None
  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…
  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
  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
  64. communication • good solution: use a shared service • straighforward

    to use to just share data between controllers • simply store the data or functions
  65. communication app.service('AuthStore', function (){
 this.getUser = function () { …

    };
 this.storeUser = function () { … };
 });
  66. communication • good solution: observer pattern • well known •

    easy to implement • no performance hit • good for observing changes in the data
  67. communication AuthStore.addObserver(doSomething);
 $scope.$on('$destroy', function () { AuthStore.removeObserver(doSomething); });

  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
  69. Michał Miszczyszyn JavaScript developer at The Comet Cult
 @mmiszy
 michal@miszczyszyn.com

  70. AngularJS caveats

  71. Thank you!

  72. Questions?