Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent clicks to custom button component in Angular 4

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;
  ...
}
like image 636
tobyb Avatar asked Jan 27 '23 23:01

tobyb


1 Answers

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.

like image 83
Brian Corcoran Avatar answered Jan 31 '23 22:01

Brian Corcoran