OnClick into ViewChild

#1

Hey there!

There is a way to attach an event to a ViewChild element?

I’m trying to do something like this:

//login.html
<button #btnLogar id="btnLogar" ion-button>LOGIN</button>

//login.ts
@ViewChild('btnLogar') btnLogar: HTMLButtonElement;

public ionViewDidLoad() {
     //this code above, not work
     this.btnLogar.onclick = (e: MouseEvent) => { this.btnLogar_Click(e); };

     //this code above, not work too 
     this.btnLogar.addEventListener("click", (e: MouseEvent) => this.btnLogar_Click(e));
}

public async btnLogar_Click(e: MouseEvent): Promise<any> {
    //message test
    window.alert("aloooow");

   //this function must be async, because it access API.
}

Thanks!

#2

I guess you have some reason, but why you don’t use the following syntax?

<button ion-button (click)="btnLogar_Click($event)">
    LOGIN
<button>
#3

thx for the answer @ramon

I would like do padronize all events into ts file.

There is a way to do this, or the click event only binding in html file?

#4

I don’t know. Maybe you can use Anguar’s HostListener?

Why? It’s really necessary?

#5

Yeah, because we developed a C# program that create ts file, with all events binding.

I Found this link, https://www.javascripttuts.com/global-events-and-event-delegation-in-angular-2/, but I don’t know what is “this.tmpListener”.

Can you help me with this?

#6

this.tmpListener is a self property that stores the function returned by Renderer.listen(). It is not declared in the example, but I think it is a mistake:

https://angular.io/api/core/Renderer#listen

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  private tmpListener;
  constructor (private renderer: Renderer){ }
  @ViewChild('ulEl') ulEl: ElementRef;

  ngOnInit() {
    this.tmpListener = this.renderer.listen(this.ulEl.nativeElement, 'click', this.logElement);
  }

  // Shorthand to get event.target
  logElement({target}) {
      if(target && target.nodeName == "LI") {
      console.log('Target id: ', target.id);
      // Add Business Logic here
    }
  }

  ngOnDestroy() {
    this.tmpListener();
  }
}

https://angular.io/api/core/Renderer#listen

NOTICE: Renderer is deprecated. You must use Renderer2

https://angular.io/api/core/Renderer2#listen

#7

Thanks!

But, it’s not working.

My component “this.btnLogar.nativeElement” is undefined.

I need to use other “ng” event?

Follow my code:

ngOnInit() {
    window.alert(JSON.stringify(this.btnLogar.nativeElement));
    //this.btnLogar.nativeElement is undefined, and is throwing exception
    this.tmpListener = this.renderer.listen(this.btnLogar.nativeElement, "click", this.btnLogarClick2);
  }

  ngOnDestroy() {
    this.tmpListener();
  }

  public btnLogarClick2() {
    window.alert("aloow");
  }
#8

I made it work this way:

HTML:

<button #btnTest ion-button block>Test button</button>

TS:

@ViewChild('btnTest') btnTest: any;
tmpListener: any;


[...]


ngOnInit() {
    this.tmpListener = this.renderer.listen(this.btnTest.getElementRef().nativeElement, 'click', () => {
        alert("Eureka");
    });
}

ngOnDestroy() {
    this.tmpListener();
}

The trick is use getElementRef().

1 Like
#9

Ok!

I’m going to make some test here.

#10

Dude, it works!

Thank you, so much.

One last question, If I need to bind more events, can I use the same variable (tmpListener), or I need, to declare one variable, for each event?

Thanks man.

#11

You need one variable for each event.