Create a gist now

Instantly share code, notes, and snippets.

@toddmotto /*.md
Last active Jul 1, 2018

Embed
What would you like to do?
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.

@rohitsharma1991

This comment has been minimized.

Show comment
Hide comment
@rohitsharma1991

rohitsharma1991 Apr 29, 2016

pls send the link best tutorials of angularjs basic

pls send the link best tutorials of angularjs basic

@benbrownlol

This comment has been minimized.

Show comment
Hide comment

benbrownlol commented May 5, 2016

@igorlino

This comment has been minimized.

Show comment
Hide comment
@igorlino

igorlino Aug 17, 2016

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

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

This comment has been minimized.

Show comment
Hide comment
@jagchat

jagchat 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

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

@ljelewis

This comment has been minimized.

Show comment
Hide comment
@ljelewis

ljelewis Nov 1, 2016

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.

ljelewis commented Nov 1, 2016

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

This comment has been minimized.

Show comment
Hide comment
@jamesbondo

jamesbondo Dec 2, 2016

@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.

@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

This comment has been minimized.

Show comment
Hide comment
@kulashaker30

kulashaker30 Sep 27, 2017

@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

@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

This comment has been minimized.

Show comment
Hide comment
@dody87

dody87 Oct 16, 2017

very clear!

dody87 commented Oct 16, 2017

very clear!

@zbend

This comment has been minimized.

Show comment
Hide comment
@zbend

zbend 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.

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

This comment has been minimized.

Show comment
Hide comment

victorhazbun commented Jun 4, 2018

Thank you @toddmotto (2018)

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