Tuesday, April 29, 2014

Angular Tricks and Tips, Do's and Dont's.

Using Angular In my view

Here I had listed some tips, do's, dont's to use in Angular based on my experience and some references from web, these are basically drafted for my own reference and I share this as it might be useful to others as well.

When you write something in Angular it's very easy to start, perhaps a controller and directive will let you start things.

But when you start write serious apps, the basics plays a larger role and your app can go easily wrong If the basics are not applied properly.

A break in a $scope can cause you a serious performance problems.

And when the application grows larger the separation of concerns is more important as your application
should be maintainable.

Some Tips Here

  • Controller is not the place to manipulate your DOM, use directives.
  • Services can be used to share data between controllers instead of creating inherit scope.
  • Link function in Directive is to add behaviors to your extended element.
  • Having Directives allowed as 'A' attributes allows you to add more than one behavior and reusable.
  • Can use scope.$apply to invoke Controller methods from Directive link function.
  • Can talk to DirectiveA via adding that as 'require' inside the DirectiveB and access the ControllerA as fourth param of link function from DirectiveB.
  • Use angular.extend to get Controller Inheritance.
  • Scope is not your model - a binding between Controller and model.
  • Create sub scope when invoking sub controller from your controller.
  • Single change in $scope can invoke multiple functions watch out for performance.
  • Have a service layer to perform reusable tasks.
  • Control logic in directive controller and DOM logic in directive link function, glue with scope sharing.
  • Write $watch on a scope value to make directive react to changes. when value changes all $watche observing that element are executed.
  • If the code is outside of angular scope you have to call scope.$apply to trigger the update.
  • You should have a $scope.$apply() anywhere it fires a callback.
  • $scope.$watch should replace the need for events.
  • Directives are able to directly communicate with each other through directive controllers.
  • Extend directives by using directive controllers, and can place methods and properties there and can override the same.
  • Don't wrap element inside of $() as all Angular elements are already jq-objects.
  • If you find yourself triggering the '$apply already in progress' error while developing with Angular.JS (can happen when u trigger a lot of DOM events), you can use a 'safeApply' method that checks the current phase before executing your function.
  • A must read on $scope, understanding prototypical scope and scope inheritance in Angular - https://github.com/angular/angular.js/wiki/Understanding-Scopes.
  • Parent Scope: scope: false, [Default] so no new scope at all - This is also helpful for child directives that are only used in the context of the parent directive.
  • Child Scope: scope: true - Directives with a child scope are context-aware and are intended to interact with the current scope.        
  • Isolate scope: scope: {} - This is for reusable components.     - The intent is that they are to be used for a specific purpose, so combining them with other directives or adding other interpolated attributes to the DOM node inherently doesn't make sense .       - To be more specific, anything needed for this standalone functionality is provided through specified attributes evaluated in the context of the parent scope; they are either one-way strings ('@'), one-way expressions ('&'), or two-way variable bindings ('=').
  • AngularJS allows only one isolated scope per element.
  • angular.element wraps a raw DOM element or Html String as a JQuery element.
  • In keeping with the Angular way, most DOM manipulation and 2-way binding using $watchers is usually done in the link function while the API for children and $scope manipulation is done in the controller. This is not a hard and fast rule, but doing so will make the code more modular and help in separation of concerns (controller will maintain the directive state and link function will maintain the DOM + outside bindings).
  • Modularization - Modularize your modules by creating sub modules for a root module.. something like angular.module('myApp'); [myapp.sub1, myapp.sub2]);
  • NgModelController provides an API for the ng-model directive. It specifically does not contain any logic which deals with DOM rendering or listening to DOM events. A use case for using NgModelController would be when you need to build a control other than the standard input, select, textarea, etc. In that case NgModelController is extended or complemented by the new directive. This is done by requiring ngModel in the new directive and accessing its methods through ngModel as in “ngModel.$render().” New directives using this approach provide DOM manipulation and the NgModelController methods are used to implement data-binding and data validation. 

    Interacting with NgModelController involves three related values: 
    1. The value of an element within the DOM such as element.html().
    2. $viewValue which is the NgModelController representation of the value in the DOM (which may differ from the actual DOM value). 
    3. $modelValue which is the NgModelController representation of the model’s data (which may differ from $viewValue).

  • Transclusion - the contents of a transcluded directive will have whatever scope is in the outside of the directive, and use transclusion when u want to use arbitrary contents inside and have the transclusion as a wrapper that adds some common behavior to the arbitrary content.
  • Transclusion requires the context of the scope tree, not the isolated scope of the directive. Because of that, transcluded content scope is not the child of the directive scope, it is instead a child of the directives parent scope, effectively making it like the directive scope does not exist in the inheritance chain.
  • When you have to deal with some Html DOM/Node level manipulations before using a plain JS be conscious about the angular provided JQlite api functions. Have a look here.  https://gist.github.com/esfand/9638882