tl;dr - How do I get the click()
handler on the myButton component to honor the disabled state of the button?
I have a custom button component that's used to componentize buttons of similar look and feel, including text and FA Icons. The button component gets fed certain inputs, including its text and a flag for whether or not its disabled. When disabled, it displays correctly (i.e. dimmed and the no-smoking cursor), but its click()
handler always receives the click.
I think I know why this is happening, but I don't know how to fix it. I've tried declaring an Output() click = new EventEmitter<any>()
on the button component thinking that somehow Angular would wire it up correctly but that didn't work.
The consumer of my button would do so with something like this:
//foo.component.html
...
<my-button
(click)="saveWidget()"
[disabled]="shouldBeDisabled"
type="{{buttonTypes.save}}">
</myButton>
...
//foo.component.ts
import { ButtonTypes } from './myButton';
export class FooComponent implements OnInit {
buttonTypes = ButtonTypes;
saveWidget() {
//do some saving
}
get shouldBeDisabled() {
return true; //Normally a real test in here
}
...
}
My problem is that when this button is used, the click handler (i.e. saveWidget()
on foo.component) is being invoked regardless of the my-button
's disabled state.
The button component looks something like this:
export enum ButtonTypes {
add,
cancel,
save,
}
@Component({
selector: 'my-button',
template: `<button [type]="tagType"
[disabled]="disabled"
[ngClass]="btnClasses">
<i *ngIf="hasLeft" class="fa" [ngClass]="iconCls" aria-hidden="true"></i>
<span class="hidden-xs hidden-sm">{{text}}</span>
<i *ngIf="hasRight" class="fa" [ngClass]="iconCls" aria-hidden="true"></i>
</button>`
})
export class ButtonComponent implements OnInit {
@Input() disabled = false;
@Input('type') btnType: ButtonTypes;
@Input() color?: ButtonColor;
@Input() size?: ButtonSize;
...
}
You can use @HostBinding('class')
and :host
-selectors to disable clicks via pointer-events: none
based on your shouldBeDisabled
property:
//foo.component.scss
:host(.disabled) {
// Disable click event.
pointer-events: none;
}
:host(.enabled) {
// No customizations.
}
//foo.component.html
...
<my-button
(click)="saveWidget()"
[disabled]="shouldBeDisabled"
type="{{buttonTypes.save}}">
</myButton>
...
//foo.component.ts
import { ButtonTypes } from './myButton';
export class FooComponent implements OnInit {
@HostBinding('class')
get hostClass(): string {
return this.shouldBeDisabled ? 'disabled' : 'enabled';
}
get shouldBeDisabled() {
return true; //Normally a real test in here
}
...
}
I found Learning Angular: Conditionally add styles to an element to be very useful to work through a similar issue.
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