Reputation: 2721
I have a custom button component, like this (simplified):
@Component({
selector: 'my-button',
template: `
<button (click)="handleClick($event)">
<ng-content></ng-content>
</button>
`
})
export class MyButtonComponent {
@Output() public onClick: EventEmitter<Event> = new EventEmitter();
handleClick(e) {
this.onClick.emit(e);
}
}
Normal use case for the button is for user to attach an onClick
handler. However, some users will want to use button as a link instead, like this:
<my-button [routerLink]="'/dashboard'">Go to dashboard</my-button>
What I'd like to do in this case is render my-button
as an <a>
element instead of literal <button>
. But in order to do that, I need to detect that user has attached the [routerLink]
directive to it.
Is there any way to do that?
I know I can just add a boolean @Input()
prop that will switch the rendering to <a>
mode, but that feels clunky.
Upvotes: 1
Views: 360
Reputation: 5470
You would have to use @Optional
and @Host
both are located in @angular/core
.
On your my-button
component for typescript you would need to do dependency injection like so:
export class MyButtonComponent implements OnInit {
constructor(@Optional() @Host() routerLink: RouterLink) {
console.log(routerLink)
}
...
}
Then on your template you can check if either routerLink
is null or not and render either <a>
tag or <button>
tag
Edit:
To get link working you would need to do this:
<a [routerLink]="routerLink.commands">
Test
</a>
Unfortunately I wasn't able to get <ng-content>
working in a
tag for some reason.
Edit 2:
Reason why ng-content
wasn't working is due to multiple ng-content
in the component, one way to solve this is to use ng-template, for example:
<ng-container *ngIf="hasRouterLink">
<a [routerLink]="routerLink.commands">
<ng-container *ngTemplateOutlet="contentTpl"></ng-container>
</a>
</ng-container>
<ng-container *ngIf="!hasRouterLink">
<button>
<ng-container *ngTemplateOutlet="contentTpl"></ng-container>
</button>
</ng-container>
<ng-template #contentTpl><ng-content></ng-content></ng-template>
Upvotes: 5
Reputation: 61
Do you plan to add something bigger than just text as you ng-content
or there will be some complicated logic for onClick
?
I think your case is pretty common and usually it's solved by creating css classes to make buttons and links looks the same. And you can use <a>
or <button>
depends on situation and just add necessary classes
Upvotes: 0