Reputation: 173
I am trying to create a component in Angular 5 that will house a reusable template for a button. In different parts of my app buttons will call different functions, so I would like to be able to tell the given instance of the button what function to call. I know I could create an HTML tag for a button wherever I need it, but I was hoping I could create a reusable component so I can ensure formatting is consistent throughout the app.
Error
Got interpolation ({{}}) where expression was expected at column 0 in
[{{functioncall}}]
Component
<div id = "button">
<button type="button" class= "btn" (click) ="{{functioncall}}" >{{label}}</button>
</div>
And HTML
import { Component, OnInit, Input } from '@angular/core';
@Component({
selector: 'app-button',
templateUrl: './button.component.html',
styleUrls: ['./button.component.css']
})
export class ButtonComponent implements OnInit {
@Input() label:string;
@Input() functionCall:string;
constructor() { }
ngOnInit() {
}
}
Upvotes: 17
Views: 36394
Reputation: 1
This implementation allows for direct access to the host events using @HostListener without the need to add additional HTML elements such as divs or buttons within your template just to be able to access these events.
Here's an example of its usage
app.component.html
<app-button (app-mousedown)="navigateHome()">Click Me!</app-button>
button.component.ts
import { Component, EventEmitter, HostListener, Input, Output } from '@angular/core';
import { LoadingSpinnerComponent } from '../loading-spinner/loading-spinner.component';
@Component({
selector: 'app-button',
standalone: true,
imports: [LoadingSpinnerComponent],
templateUrl: './button.component.html',
styleUrl: './button.component.scss',
})
export class ButtonComponent {
@Input() loading = false;
@Output('app-mousedown') event = new EventEmitter<MouseEvent>();
@HostListener('mousedown', ['$event'])
handleMousedown(event: MouseEvent) {
this.event.emit(event);
}
}
button.component.html
@if (loading) {
<app-loading-spinner [width]="17" [height]="17" [borderWidth]="2" />
} @else {
<ng-content> </ng-content>
}
button.component.scss
@import "../../styles.scss";
:host {
position: relative;
display: flex;
padding: 10px 30px;
justify-content: center;
align-items: center;
width: fit-content;
border-radius: 10px;
font-size: 15px;
min-width: 100px;
min-height: 40px;
outline: none;
margin-right: 7px;
overflow: hidden;
transition: background-color 0.1s ease;
background-color: white;
outline: 1px solid $color;
cursor: pointer;
&:hover {
background-color: rgb(239, 243, 246, 0.8);
}
}
Upvotes: 0
Reputation: 2953
Reusable Component - it's work for me
I have created button as reusable component
button.component.html
< button type="button" class= "btn" >{{label}} < / button >
button.component.ts
export class ButtonComponent {
@Input() label: string;
@Output() onClick = new EventEmitter<any>();
constructor() {}
onClickButton(event) {
this.onClick.emit(event);
}
}
user.component.html
< app-button (click)="functioncall($event)" [label]="label"> < /app-button >
user.component.ts
label = 'Hello World';
Upvotes: 1
Reputation: 4963
In addition to @miladfm answer, I'd recommend using the <ng-content></ng-content>
directive here to pass content through instead of pulling in {{label}}
, assigning the @Output
decorator to click
instead of onClick
, and using the MouseEvent
type instead of any
. Using these changes will allow the button component to behave syntactically more like a native button when it's consumed:
button.component.ts
...
@Output() click = new EventEmitter<MouseEvent>();
onClickButton(event) {
this.onClick.emit(event);
}
...
button.component.html
<div id = "button">
<button type="button" class="btn" (click)="onClickbutton($event)">
<ng-content></ng-content>
</button>
</div>
parent.component.ts
...
functioncall(e: MouseEvent) {
// do stuff
}
...
parent.component.html
<app-button (click)="functioncall($event)">Your Label Here</app-button>
Upvotes: 11
Reputation: 1526
you have to use the @Output
decorator to emit some event (from child to parent)
button.component.ts:
@Input() label: string;
@Output() onClick = new EventEmitter<any>();
onClickButton(event) {
this.onClick.emit(event);
}
button.component.html:
<div id = "button">
<button type="button" class= "btn" (click)="onClickbutton($event)" >{{label}}</button>
</div>
parent.component.ts
label = "button label"
functioncall(event) {
console.log('functioncall', event);
}
parent.component.html
<app-button (onClick)="functioncall($event)" [label]="label"></app-button>
See example: https://stackblitz.com/edit/angular-gghsax
Upvotes: 24