93

I do not quite understand when to use a directive and when it would be more appropriate to use nginclude. Take this example: I have a partial, password-and-confirm-input-fields.html, that is the html for entering and confirming a password. I use this both under signup-page and under change-password-page. Those two pages has a controller each, the partial html has no dedicated controller.

Should I use directive or ngInclude for this?

Andrew Tobilko
  • 44,067
  • 12
  • 74
  • 128
EricC
  • 5,100
  • 9
  • 44
  • 68
  • I'd go with a directive every time, but I'm curious what more experienced Angular folks would say. – Austin Mullins Jun 11 '14 at 20:24
  • 1
    If it's truly an independent component, it should probably have it's own controller associated with it. IMO, I'd use a partial - but, I'm curious for some more input – tymeJV Jun 11 '14 at 20:26
  • 4
    If there is any js code needed for that partial, use a directive. If it's just HTML, use ngInclude. – Daniel Beck Jun 11 '14 at 20:30

1 Answers1

122

It all depends on what you want from your code fragment. Personally, if the code doesn't have any logic, or doesn't even need a controller, then I go with ngInclude. I typically put large more "static" html fragments that I don't want cluttering up the view here. (ie: Let's say a large table whose data comes from the parent Controller anyway. It's cleaner to have <div ng-include="bigtable.html" /> than all those lines cluttering up the View)

If there is logic, DOM manipulation, or you need it to be customizable (aka render differently) in different instances it's used, then directives are the better choice (they're daunting at first, but they're very powerful, give it time).

ngInclude

Sometimes you will see ngInclude's that are affected by their exterior $scope / interface. Such as a large/complicated repeater lets say. These 2 interfaces are tied together because of this. If something in the main $scope changes, you must alter / change your logic within your included partial.

Directives

On the other hand, directives can have explicit scopes / controllers / etc. So if you're thinking of a scenario where you'd have to reuse something multiple times, you can see how having its own scope connected would make life easier & less confusing.

Also, anytime you are going to be interacting with the DOM at all, you should use a directive. This makes it better for testing, and decouples these actions away from a controller / service / etc, which is something you want!

Tip: Make sure not to use restrict: 'E' if you care about IE8! There are ways around this, but they are annoying. Just make life easier and stick with attribute/etc. <div my-directive />

Components [Update 3/1/2016]

Added in Angular 1.5, it's essentially a wrapper around .directve(). Component should be used most of the time. It removes a lot of boilerplate directive code, by defaulting to things like restrict: 'E', scope : {}, bindToController: true. I highly recommend using these for almost everything in your app, in order to be able to transition to Angular2 more easily.

In conclusion:

You should be creating Components & Directives a majority of the time.

  • More extensible
  • You can template and have your file externally (like ngInclude)
  • You can choose to use the parent scope, or it's own isolate scope within the directive.
  • Better re-use throughout your application


Update 3/1/2016

Now that Angular 2 is slowly wrapping up, and we know the general format (of course there will still be some changes here and there) just wanted to add how important it is to do components (sometimes directives if you need them to be restrict: 'E' for example).

Components are very similar to Angular 2's @Component. In this way we are encapsulating logic & html in the same area.


Make sure you encapsulate as many things as you can in components, it will make the transition to Angular 2 that much easier! (If you choose to make the transition)

Here's a nice article describing this migration process using directives (very similar if you were going to use components of course) : http://angular-tips.com/blog/2015/09/migrating-directives-to-angular-2/

danronmoon
  • 3,613
  • 5
  • 32
  • 55
Mark Pieszak - Trilon.io
  • 44,537
  • 13
  • 74
  • 89
  • 5
    I agree with this answer. The learning curve for directives is steep, but it really pays off once you get it. – Jazzy Jun 11 '14 at 20:53
  • @mcpDESIGNS, one case that perhaps does not fit this answer perfectly (at least not the two first paragraphs). If I have a nav-partial, with its own controller, and I will only use this once (in the index.html-file), then this probably should be a partial and not a directive since it is used only once (it is kind of a separate app in the sense that it is not included as a part of the ngview), even if it has its own logic. Or? – EricC Jun 12 '14 at 04:56
  • This is still confusing.. you can also specify a controller when using ngInclude, look at this : http://stackoverflow.com/questions/13811948/different-ng-includes-on-the-same-page-how-to-send-different-variables-to-each/13812605#13812605 – Marwen Trabelsi Mar 30 '15 at 17:31
  • 1
    Of course, but it's always completely connected to the parent controller in some way. Where a directive can *create* a controller within itself for when the template is loaded. It can be completely separate (if you want) – Mark Pieszak - Trilon.io Mar 31 '15 at 13:58
  • My biggest problem with directives so far is with they way they are rendered: always. If I create a page with several tabs, I (often, not always) want that tab to be loaded and rendered only when it is shown. But directives are loaded immediately. It also makes them practically unusable for recursive applications (like treeviews). For these cases, includes seem to work much better. – Arwin Jan 22 '16 at 09:43
  • You can use `ng-if` to decide whether a directive should be rendered @Arwin unlike `ng-show`, `ng-if` doesn't let the underlying Angular code to be generated – Mark Pieszak - Trilon.io Jan 22 '16 at 15:12
  • My apologies, that might not stop them from "loading" look at this implementation: http://stackoverflow.com/questions/14904139/wait-to-load-angularjs-directive-template Basically you have to actually decide when to load the template with $http and $compile it. Forgot I use this same concept myself sometimes! @Arwin – Mark Pieszak - Trilon.io Jan 22 '16 at 16:42
  • Exactly, that's my problem with them at the moment. I'd prefer a much more straightforward setting on the directive to control this. – Arwin Jan 23 '16 at 17:31
  • 1
    Best thing you can do is abstract this concept into a factory or something, that way you can just call it from within a `link` function and voila! It would of been nice baked into directives though, without a doubt :( @Arwin – Mark Pieszak - Trilon.io Jan 23 '16 at 17:34
  • in your answeryou say that it's unsafe to use directive with "E" option in ie8. But in the update you said that components are defined with the "E" option in mind. That's the same with components or they have a workaround out of the box? – netalex Oct 21 '16 at 16:17
  • @netalex I believe unfortunately if you're worried about IE8 then it'll still be a problem, yes it just defaults to the E option :( although IE8 was dropped at 1.3 so can't imagine there are many people still worried about that? – Mark Pieszak - Trilon.io Oct 22 '16 at 00:53