Skip to content

Instantly share code, notes, and snippets.

@wizardnet972
Created March 5, 2017 06:17
Show Gist options
  • Save wizardnet972/f2d9efd6aa6d96a7a2e855f15e9bcd01 to your computer and use it in GitHub Desktop.
Save wizardnet972/f2d9efd6aa6d96a7a2e855f15e9bcd01 to your computer and use it in GitHub Desktop.
Component versus Directive in AngularJS

Component versus Directive in AngularJS

.component()

Components are not "helper" methods, they are the best change in Angular 1.x since I've been using it.

What is the role of .component()?

  • Declares new HTML via a template or templateUrl
  • Should be used to create Components as part of a Component architecture
  • To bind view logic to HTML
    • Such as ng-click="ctrl.myFn()"

How can I use .component()?

  • Components should be used with one-way data-binding expressions, such as bindings: { prop: '<' }
  • Templates can be a String literal or a function that returns a template for compilation
  • Template functions pass in $element and $attrs for manipulating the DOM before compilation (rare use case)
  • Isolate properties passed down into bindings: {} should use '<' to pass data one-way
  • Delegate event functions should be passed down bindings: {}, and should use '&' expression
  • The $onChanges lifecycle hook
    • Should clone the a one-way binding property, making it immutable (passed as a change Object hash in the args)
    • The clone should be assigned to the local Component's Controller
    • Mutations should only occur on the local clone
    • Data should be passed back up using delegated & function
    • Access the custom Object data using $ctrl.method($locals); or $ctrl.method($event); in the parent Component
    • Rebind accordingly
  • The $onInit lifecycle hook
    • Use for initialisation logic
    • Also use for inheriting parent Controller behaviour through require: {} (as Object syntax)
  • Replace any $scope.$on('$destroy') instances in your Controller with $onDestroy() lifecycle hook
  • Use $postLink for DOM manipulation
    • DO NOT just convert Directives over and hack them into Controllers, this is not what $postLink is for
    • Let's assume we have a <ul> Component, and for some reason I wanted to do something with the <li> elements that are dynamically generated from ng-repeat for example, you could use $postLink to query the DOM here, and do something on a higher level (something that binding a Directive directly to each <li> cannot achieve
  • Two-way data-binding should only be used with ngModel
  • Component Controllers are entirely optional, you can create Stateless (Dumb) Components

When should I start using it?

Yesterday!

.directive()

Directives and templates/controllers are not necessary anymore, however the API remains consistent for backwards compatibility. Use a Directive for binding custom behaviour to existing DOM.

What is the role of .directive()?

  • A Directive decorates the DOM, it adds behaviour and extends existing DOM. When you use a .component(), you create DOM, when you use .directive() you decorate DOM, that is the mindset
  • You already know ng-click, it's a Directive, therefore it decorates and adds existing behaviour to an existing element, it is not <ng-click> as an Element

How can I use .directive()?

  • Directives should be used when you need to conduct DOM manipulation outside of the Angular event loop and core
  • Use the compile and/or link function to create the custom functionality you require
  • Ensure you unbind custom events or DOM APIs such as element.addEventListener(); inside the $destroy event
  • Obtain access to attributes and use $observe depending on what you need to access (readonly values/etc)
  • If using a Controller, use as fourth link: fn argument, and only update view logic inside the Controller
  • Never pass $scope for manipulating your data, always use fourth argument $ctrl (if using a Controller, depends on use case)
  • Require and manipulation other Directives using require property as String or Array syntax

Practices

What should I restrict my Components/Directives to?

  • .component() is restricted to 'E' by default, meaning custom element, you cannot change this.
  • .directive() should decorate, therefore should be an attribute only, meaning restrict: 'A' always

If you want to learn much more and build an decent sized app with full Component architecture, one-way bindings and event flow (and all of the above) - I'm building out a course on exactly this right now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment