Rainbow Coding

Introducing Angular 1.5 component, $onInit and one way bindings

One of the most difficult to grasp things with angular has been directives. In this article we take a look how angular 1.5. simplifies them.

One of the most difficult to grasp things with angular has been directives. There are couple of problems with them:

  • It’s uncommon name from other frameworks and therefore difficult to wrap your head around
  • Syntax has many switches that depend on your angular version
  • Lifecycle is complex with all the compile, link, controller hooks, leaving you wondering what goes where

Directives used to be the way to do reusable html elements, but most of the time you don’t need to use the special directive features. Sometimes you could see crazy looking directives.

angular.module('reverseModule', [])
.directive('reverseName', function() {
  return {
    template: '<span></span>',
    scope: {
      name: '='
    },
    restrict: 'E',
    compile: function() {
      return function(scope, elem, attrs) {
        scope.element = elem.find('span');
      };
    },
    controller: function($scope) {
      $scope.element.html(scope.name.reverse());
    }
  };
});

The above syntax makes things look much more complicated than they are.

Basically all that achieves, is making a one way binded reverse name component that can be used as below.

<reverse-name name="otto"></reverse-name>

Of course there are simpler ways to write the above, especially after angular 1.3 introduced one way bindings it could be written as.

angular.module('reverseModule', [])
.directive('reverseName', function() {
  return {
    restrict: 'E',
    template: '<span>{{::reversedName}}</span>',
    scope: {
      name: '='
    },
    controller: function($scope) {
      $scope.reversedName = scope.name.reverse();
    }
  };
});

Luckily, angular 1.5 introduced the new component syntax, which essentially is simplified directive.

angular.module('reverseModule', [])
.component('reverseName', {
  template: '<span>{{$ctrl.reversedName}}</span>',
  bindings: {
    'name': '<'
  },
  controller: function() {
    this.$onInit = function() {
      this.reversedName = this.name.reverse();
    };
  }
});

If you compare that with the directive above, it looks much more understandable.

The component example also introduced two other very useful angular features. Those are $onInit hook and one way binding (‘<‘). $onInit hook ensures that the component is mounted and ready before it is executed. This can help avoid strange errors caused with parent/child relations.

Another is the one way binded name, by using ‘<‘ syntax. This will ensure that you cannot accidentally overwrite the parent values. This is especially helpful for view/show type components, that should not change the parent’s values.

The usage of all of the above examples is same.

© RainbowCoding 2010-2023