Suppose one has two predefined directives dir1
and dir2
( which are provided by a 3rd party API that one has no control over). Let's say these can be applies to an html element as follows:
<div dir1="red" [dir2]="123">... My Content ...</div>
I have found myself applying the above the directives with the exact same binding values in several places in my code. Rather than repeat myself, I would like to create my own custom directive, call it myDir
, that I could apply like this:
<div MyDir >... My Content ...</div>
This should be exactly the same as applying dir1
and dir2
as in the prior example above i.e. it will have the values "red"
and 123
hard coded within it's class.
I have tried setting host bindings as in the following plunker example, but this doesn't work..
One idea I have is if only typescript had multiple inheritance, then I would simply write the MyDir
class an extension of Dir1
and Dir2
..
My question is how do I go about writing the custom directive (MyDir
) to achieve the intended use?
Kindly Assist, Thanks You!
https://plnkr.co/edit/W20Wvew326qsGfPU5H6v
This error occurs when multiple directives are applied to the same DOM element, and processing them would result in a collision or an unsupported configuration. To resolve this issue remove one of the directives which is causing the collision.
You can not use two structural directives on the same element. You need to wrap your element in another one. It's advised to use ng-container since it wont be rendered in DOM.
Structural directives are directives which change the DOM layout by adding and removing DOM elements. Angular provides a set of built-in structural directives (such as NgIf , NgForOf , NgSwitch and others) which are commonly used in all Angular projects. For more information see Built-in directives.
To apply multiple directives we'll have to either (a) expand the sugared syntax, (b) nest template tags or use the <ng-content> tag. It is important to note, that like the ng-template elemement, ng-container elements are not rendered to the DOM, but rather their child(ren) are/is.
Update: Still not possible in May 2020. It is on the Angular Team's feature backlog. Follow progress here https://github.com/angular/angular/issues/8785
The following is what ended up being my solutions for the problem, as presented above. Note that this is not the most general solution; In other scenarios, it's adaptability will depend largely one what the public API of the directives involved looks like. It should work well where the directives to be combined have atleast ElementRef
as one of the injection dependencies like:
constructor(private elRef: ElementRef, /*...*/) { /*...*/ }
This may well be the case if the directives are responsible for changing the styling of an element.
What I did was, I simply created two new
Dir1
/Dir2
objects passing in the MyDir
's ElementRef
as context for Dir1
/Dir2
like so:
// inside MyDir constructor
this.d1 = new Dir1(this.elRef, /*...*/);
this.d2 = new Dir2(this.elRef, /*...*/);
Then I set the public properties (@Input
bindings) of d1
/d2
to values I need them to permanently be (to avoid repeating myself):
//inside MyDir constructor
this.d1.dir1 = "red";
this.d2.dir2 = 123;
Next, all I had to try and do was match up the public methods d1
/d2
with MyDir
by invoking the former's methods inside the corresponding method(s) of the latter, e.g.
ngAfterContentInit() {
this.d1.ngAfterContentInit();
this.d2.ngAfterContentInit();
}
Here is the plunker with this all pieced together https://plnkr.co/edit/TCagW8vOPrqSiOT9Oztf
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With