18

I know that in ng2 we have ComponentFactoryResolver that can resolve factories that we can apply to a ViewContainerRef.

But, is there something similar for directives? a way to instantiate them and apply them to the projected content from a component?

lqbweb
  • 1,684
  • 3
  • 19
  • 33
  • 1
    I have actually no idea about this, but seeing that directives are very similar to components, does using the component factory not work for directives? – poke Sep 19 '16 at 06:21
  • 1
    it does not work, it would have to be added to the entryComponents of the module (as, entryComponents does not exist for the Directive decorator), and it does not like it. – lqbweb Sep 19 '16 at 12:51
  • This can be helpful. [How to dynamically add a directive?](https://stackoverflow.com/questions/41298168/how-to-dynamically-add-a-directive) – Berkin Sansal Feb 04 '22 at 08:39

2 Answers2

16

No, directives can't be added or removed dynamically. They are only applied to HTML statically added to component templates.

What you could do is to enable/disable the directive by passing a parameter (@Input()) to the directive to notify it to do something or not.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • 2
    then, if I have a TemplateRef, it should be possible to modify it manually with jQuery or something, so that it also instantiates another directive when it gets projected right? – lqbweb Sep 19 '16 at 12:54
  • 2
    I don't think so. `TemplateRef` is never added to the DOM. It is only used internally by Angular, therefore you can't use it with jQuery. Adding some HTML dynamically, even when it matches some directive selector, still doesn't instantiate a directive. – Günter Zöchbauer Sep 19 '16 at 12:56
  • 3
    so basically, there is really no way in ng2, to actually make a directive that apply others right? this is driving me nuts. I can not wrap existing components that project views, into others. Simply not supported? – lqbweb Sep 19 '16 at 12:59
  • 1
    I don't understand " I can not wrap existing components that project views, into others.". Perhaps you can edit your question and demonstrate what problem you actually try to solve. – Günter Zöchbauer Sep 19 '16 at 13:01
  • 1
    I think better to leave this concise and as it is. I have actually already published another question with my actual problem, have a look please to the plunkr that I link here: http://stackoverflow.com/questions/39557919/compile-template-before-projecting-the-content-dynamic-projecting – lqbweb Sep 19 '16 at 13:03
  • 2
    There is an open issue on github regarding this https://github.com/angular/angular/issues/8785 – Touqeer Shafi Aug 04 '17 at 07:03
  • What If I need to "combine" multiple directives? Eg I am using material components directives X Y Z and that repeats plenty of times across the application. Can I replace that directive with COMBINED directive that will apply XYZ out of the box somehow to host element? – Antoniossss Aug 28 '20 at 09:13
  • @Antoniossss I don't follow Angular that closely as I did back then, but I don't think there was a way to accomplish that, except perhaps wrapping it in a new component. I wouldn't excpect this to have changed since, but I don't know for sure. – Günter Zöchbauer Aug 28 '20 at 11:59
  • 1
    @GünterZöchbauer this is what I am thinking as well. Thanks for your feedback – Antoniossss Aug 28 '20 at 13:04
4

It's not impossible. It's just ugly and error prone. Basic thing to remember is that a directive is first a class. If you can manually get your hands on the stuff the constructor needs, you can simply do something like:

const highlight = new HighlightDirective(...);

Be prepared for possibly running into unexpected behaviors as you will escape Angular's hands.

Read my full answer here on dynamically adding directives.

Shy Agam
  • 1,285
  • 1
  • 13
  • 37