Tuesday, 10 June 2014

AngularJS best practices and information in a nutshell

1.       Minification Process
a.       Remove white space and shorten parameter and variables
b.      Manually minify and the resulting file should be min safe - Dependencies are mentioned explicitly within [] brackets.
c.       Use ngmin - but this has an issue when using function names in place of inline functions.
d.      Use an external minifier and choose what we want to minify

2.       Controllers
a.       Setting up scope and manage interaction between view and model
b.      There should not be too many collaborators in a single controller. If there are many collaborators, we should divide the logically related collaborators into one collaborator/service and use it as a single entity.
c.       If there is any global dependency on the controller, we should create a service using (.value) and use it as a dependency.

3.       Services
a.       Handle Non-view data
b.      Communicate with the server
c.       Hold state and logic
d.      There are 5 ways to create a service
                                                               i.        Value
                                                             ii.       Constant
                                                            iii.       Factory (returns the value/object and caches it)
                                                           iv.       Service (does a new on the function and returns and caches it, should be used only when we have existing classes which we want to use
                                                             v.       Provider - this is configurable, must have $provider as a dependency as we use the provide method, must return $get and can be configured before running
e.      All services are singleton and once configured there is no way to go back.
f.         Filters are also services with specific naming format
g.        Mostly we write services of the following types:
                                                               i.       Factories
                                                             ii.       Services holding state
                                                            iii.       Simple functions as services

4.       Directives
a.       Taking care while naming directives as there might be conflict arising due to same name existing angular directives or in HTML where there are existing attributes. Angular does not know these naming conflicts and will not throw any error always. It will simply not work.
b.      Camel casing while creating a directive and snake casing.
c.       While using the directive, we should uniquely name our directives by applying some prefix specific to the functionality that the directive is trying to achieve.
d.       Directives are used for the following purposes
                                                               i.       Widgets - may or may not be reusable
                                                             ii.       Manipulate DOM
                                                            iii.       Functionality
e.       We can add functionality to a directive by using the controller or the link function. They are same and can be used interchangeably. But, as we use scopes, controller is the default choice. We can reuse controllers also by declaring it separately and use it inside the directive.
f.        We can indicate that a controller is required in a directive by using the require property in a directive. We can use prefix the controller name with '^' if it is from a parent directive or '?' if null is returned in case the controller is not found.
g.        Directive interfaces
                                                               i.       Shared scope
                                                             ii.       Inherited scope
                                                            iii.       Isolated scope
h.      Isolated scope is better than inherits scopes because in inherited scope all the parent objects are visible to the child scope and thus it gives way to tight coupling.
5.       FOUC - Flash of uncompiled components - Curly braces are displayed when the page is loaded as angular could not apply the bindings by then. It is a concern when the page is loading and data is loading.
a.       Resolution
                                                               i.       ngCloak(Change both the view and CSS)
                                                             ii.       ngBind
                                                            iii.       Waiting image
                                                           iv.       We can add a boolean property in the service result (for data loading) and add ng-hide in the image and set it to the property in scope.
6.        Writing valid HTML
a.        Switch the directives as classes or comments or attributes.
b.       Add the data- in the attribute directives.
c.        Don’t use element directives.
7.       Directives help us to use HTML as Domain Specific functionality by encapsulating specific domain activities into directives.

8.       Scopes

a.       Use Batarang as a Chrome plug in to debug issues in an angularjs application
b.      Scopes can be created as a shared scope, inherited scope or isolated scope. In shared scope both parent and child can access each other, in inherited scope child can access parent but parent cannot access child. In isolated scope, both parent and child are isolated - although the child can access parent but it can do so using a different name.
c.        To create inherited scope, set scope property to true in the directive, to create an isolated scope set scope property to any object which we want to access from the scope. Only this property will be visible in the new scope and this object is same as the object in the parent scope object.
d.      Directives can share scope with the controller and two directives can share scope with each other. Two different scopes cannot be created on the same DOM element.
e.      Use at least one object (like object.property) in the binding using ngModel (important)

9.       Communicating between components
a.        Inherited scopes
                                                               i.       If two or more child scopes need to share data which is simple in nature, we can use this. But, we should not use this very frequently as it leads to tight coupling between parent scope and child scopes.
b.       Events with $rootscope
                                                               i.       If direct descendants of rootscope need to communicate, we can use the $broadcast of the $rootscope and listen to events in the direct child elements. But, as the applications grow bigger and complexity increases this is not the right choice as it is very difficult to refactor the code with events.
c.        Services
                                                               i.       Services are singletons, so using services two child scopes can communicate easily. But this requires a lot of configuration and can be overkill if the type of communication is simple.

10.   Dividing the page into components
a.       Create a controller for each functionality and not include all functionality in a single controller.
b.      Divide the page into partial and use ng-include to include the partial and the ng-controller to add the associated controller. The controller can be added as ng-include in the partial also if we want a single controller for a partial. If we want multiple controllers to act for a partial we add it after ng-include in the main page using ng-controller.
c.       Create directives for the partials and use inherited shared or isolated scope to share data. Use isolated scope if we want the reuse the directive in any page and use require property.
d.       The above three steps created abstraction and increase cohesiveness - which are good software design principles

11.   Communicating with the server
a.       We can create a restful service using $resource. We need to add reference to the angular-resource js file and the ngResource should be added as a dependency.
b.       On $resource, we can query and it returns a $promise. After the promise is fulfilled, we can call "then" and write a callback function with the data returned from the service as a parameter.
c.       We can use $http and $q to get and write data.
d.       $resource, $http and $q - all return $promise, but the properties and methods of $promise is different for all these. So, these can be used interchangeably but require some additional code modification when we switch from one promise to the other.
e.      We can set httpheaders, caching etc using configuration while using $http etc.
f.        We can transform a request and response to add additional properties/values to the request sent by $http and the response received. This transform can be introduced before the default transform of angular or after the default transform of angular depending upon the situation. For example a build in angular transform does JSON serialization and deserialization. Transform is generally used per request.
g.        Interceptors can also be user to modify data before it is sent or after it is received. Interceptors are generally using application wide.
h.      Restangular library can be used while communicating with the server. It has different way of getting and saving data in terms of syntax but is helpful while communicating with server.
12.   Models
a.        Models contain data and state. It may contain Business logic can be cached and used for change notification when it changes.
b.      We can create models using $http or $resource. While creating models from $resource, we get a handle to the constructor function and can add further to the prototype.
c.        We can create models suing Restangular using "extendModel" function.
d.      We can build rich models using BackBone as well as Breeje. Breeje works very well with angularjs