Skip to content

Instantly share code, notes, and snippets.

@toddmotto
Last active April 25, 2023 09:06
Show Gist options
  • Save toddmotto/5b4de6c777d3e446e6410fdadb824522 to your computer and use it in GitHub Desktop.
Save toddmotto/5b4de6c777d3e446e6410fdadb824522 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've built out 3x AngularJS courses course on exactly this right now.

@rohitsharma1991
Copy link

pls send the link best tutorials of angularjs basic

@benbr-personal
Copy link

benbr-personal commented May 5, 2016

@igorlino
Copy link

Below is a versy new free tutorial/guide about how to work and migrate to components in angular 1.x

http://teropa.info/blog/2015/10/18/refactoring-angular-apps-to-components.html

@jagchat
Copy link

jagchat commented Oct 9, 2016

I have come across these list of videos on Angular JS. Pretty well presented and in great detail/depth: https://www.youtube.com/playlist?list=PLvZkOAgBYrsS_ugyamsNpCgLSmtIXZGiz

@lukenofurther
Copy link

I wouldn't say that directives "are not necessary any more". In my situation, I cannot use a component because I have to use restrict: A to insert the template tr/tbody into a table. With a component I must use a non-tr/tbody element name and the browser removes the element from the table on first page load.

If anyone knows of a smart way around this to enable a component to be used in this situation, I'm all ears.

@jamesbondo
Copy link

@ljelewis, you need a better description of your question. I'm curious.
My current project is using lots of components, they are handy, works much better than directives.

@kulashaker30
Copy link

@ljelewis, my impression on your scenario is you have templates for editing and just for displaying on a table row fashion.. it’s not complicated I think, you can use ‘ng-switc on’ depending on the mode(edit/display) of the row

@dody87
Copy link

dody87 commented Oct 16, 2017

very clear!

@zbend
Copy link

zbend commented Oct 20, 2017

Where do you put DOM manipulation? You say don't simply recreate a directive with $postlink . . I have a directive controller that fires essentially an event that its directive listens for (in link method) to then manipulate the DOM (scroll), I can't seem to find a best practice for doing this component to directive communication.

@victorhazbun
Copy link

victorhazbun commented Jun 4, 2018

Thank you @toddmotto (2018)

@brunoluann
Copy link

Thanks, @toddmotto!

@bdsexton
Copy link

I know this is an old gist, but that "building out a course" link URL is dead. Should it be updated to something at Ultimate Courses?

@toddmotto
Copy link
Author

@bdsexton - good spot, all done :) thank you!

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