Reputation: 129
What I want to do using Angular is to create a "directive" that adds a something to my component, lets say a myPortlet
with myHasCloseButton
gives myPortlet
a close button.
<myPortlet myHasCloseButton>...</myPortlet>
I found three options how to approach this and I'm not sure which one is the correct one or if I missed a better option.
Option 1: Create a directive that does something like
this.el.nativeElement.querySelector('.myCloseButton').style.visibility = 'visible';
*ngIf
, thus forcing each myPortlet
and other components to carry a hidden myCloseButton
which feels awkward and appears to be not recommended.Option 1a:
Just like Option 1, but give the directive an boolean @Input
that switches the application of the visibility.
Presence of directive no longer sufficient, usage is now
...
Option 2:
Give myPortlet a boolean @Input
and a *ngIf
directive at the right place.
Option 2b:
"Hackily" give a string @Input
instead and check if it's empty (as that's what happens when you just give the input name without anything after) and treat it as true.
Option 3: Create a directive that actually injects the myCloseButton via something like
ElementRef.nativeElement.querySelector('.myCloseButton').addComponent(myCloseButton)
[No actual tested Syntax, just an example, not sure if addComponent is the correct function and how to use it]
Elementref
is warned against in Angular Docs, appears dangerous.myPortlet
and other components to carry a hidden myCloseButton
container.myPortlet
(or other component) no longer has control over the embedded myCloseButton
.myPortlet
and the embedded myCloseButton
(especially of myCloseButton
is something more complex).So my question is: Which is the recommended approach? Am I missing any option? Any best practices? None of those options feels right.
Upvotes: 0
Views: 963
Reputation: 8306
Using @Input()
is best for this use case.
It's simple, clean, and most importantly, it allows you to dynamically determine whether your component has a close button (a nice feature you could not get with the attribute directive). Example (this is terrible UX), but what if you only wanted to allow admin users to have a close button. Then, you could subscribe to your user service and set [hasCloseButton]="userIsAdmin$ | async"
. That's pretty powerful stuff you couldn't do (in a clean way) with an attribute directive.
Also, for testing, you can just set the input directly (testComponent.hasCloseButton = true
), rather than having to create a test host component and create one case with the directive / one without.
To summarize: using @Input()
will afford you more flexibility and make testing easier.
Upvotes: 2