Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2 remove click event binding after first click

In my application I have a button with a click even on it:

<button class="btn btn-default" (click)="doSomething()">

From within the doSomething method, is there any way to remove the (click) event from the button (so the user can't trigger the functionnality anymore?).

I tried to set a disabled prop on the button but it doesn't change Angular2 behavior.

I tryed to use (click)="doSomething($event) and then

doSomething($event) {
  // My method logic goes here
  ...
  ...
  console.log('Method Logic');

  //Attempt to overwrite click event
  let target = event.target || event.srcElement || event.currentTarget;
  this.renderer.listen(target, 'click', (event) => {
      console.log('clic block');
    });
}

But It doesn't "replace" the click event. So after that, on click, both original logic and the "click block" console log are triggered!

like image 573
BlackHoleGalaxy Avatar asked Jan 02 '17 23:01

BlackHoleGalaxy


People also ask

How to add click event to a button in angular?

Let’s add changes in the Angular component. In Html template component- app.component.html: Added click event to a button with event binding syntax i.e bracket () symbol the event name is the name of the function placed inside the bracket. This function is called when the button is clicked.

What is an event binding in angular?

Inside the button tag, we see (click)="onClick ()". This is an example of Angular’s event binding. Generally speaking, an event can be many things e.g. keystrokes, mouse movements, clicks, touches, etc.

How do I bind a button to the backend in angular?

When the user submits the button, we can then save the model to the backend server. Angular event binding syntax consists of a target event name within parentheses on the left of an equal sign, and a quoted template statement on the right.

How to display button code in angular?

In Angular application, displaying button code is placed in HTML template page i.e view. The trigger event is placed in the typescript component class. So user event information will be passed from view to component class.


3 Answers

Method 1:

You can set a boolean variable, so if the user calls the function, boolean value changes and the user will be able to call the function on click again but actually nothing will happen.

bool: boolean = true;

doSomething($event) {
  if (this.bool) {
    // My method logic goes here
    ...
    ...
    console.log('Method Logic');
    this.bool = false;
  }
}

Method 2:

You can add a condition to your html component, if specified variable (in this case bool) is true, the function is going to be executed, but only once because the bool variable will be set to false and the click function will execute nothing (null) from now on.

bool: boolean = true;

doSomething($event) {
  // My method logic goes here
  ...
  ...
  console.log('Method Logic');
  this.bool = false;
}

(click)="bool ? doSomething($event) : null"

like image 86
kind user Avatar answered Oct 23 '22 16:10

kind user


The downside of just adding a guard variable for the execution is that the actual event listener is still in place and will trigger Angular's change detection when clicked, even though it doesn't do anything.

To actually remove the event listener, you have to add it via the component's Renderer. This will return a function that removes the event listener when called:

import {Component, AfterViewInit, Renderer, ViewChild, ElementRef} from '@angular/core';

@Component({
  template: `<button #button>...</button>`
})
export class SampleComponent implements AfterViewInit {

  @ViewChild('button') button: ElementRef;
  private cancelClick: Function;

  constructor(private renderer: Renderer) {}

  ngAfterViewInit() {
    this.cancelClick = this.renderer.listen(this.button.nativeElement, 'click',
      ($event: any) => this.handleClick($event));
  }

  handleClick($event: any) {
    this.cancelClick();
    // ...
  }
}

If your goal is to just remove the event listener when the event is fired for the first time, this can be implemented as a plugin to Angular's event system. I added it as a part of my ng2-events utility library [source], which lets you now do the following:

<button (once.click)="handleClick($event)">...</button>
like image 25
kryops Avatar answered Oct 23 '22 15:10

kryops


For people dealing with Observable / Subject for handling some events :

<button (click)="clickEvents$.next($event)">
class MyComponent {
  clickEvents$ = new Subject<MouseEvent>();
  firstClick$ = this.clickEvents.take(1); // Observable of first click
}
like image 30
n00dl3 Avatar answered Oct 23 '22 17:10

n00dl3