DEV Community

Cover image for Diferentes Maneiras de Criar Eventos no Angular
Gabriel de Souza
Gabriel de Souza

Posted on

Diferentes Maneiras de Criar Eventos no Angular

Um dos aspectos essenciais em aplicações web modernas é a interatividade, e o Angular oferece várias maneiras para lidar com isso, aproveitando tanto as funcionalidades nativas do Javascript quanto as capacidades mais avançadas do framework. Neste texto, vou discutir algumas abordagens que podem ser relevantes para a interatividade de suas aplicações Angular.

Observação: Os exemplos mostrados aqui utilizam Signal Queries para a captura dos elementos HTML.

addEventListener (JavaScript Nativo)

Vamos começar com o addEventListener nativo do JavaScript, que é a abordagem mais simples e direta para adicionar eventos em elementos. Embora o Angular forneça ferramentas mais especializadas, o addEventListener ainda é uma solução válida para quem deseja uma implementação mais simplificada.

@Component({
    template: `<button #el>click</button>`,
})
export class MyComponent implements OnInit {
    el = viewChild.required<ElementRef>('el');

    ngOnInit(): void {
        this.el().nativeElement.addEventListener('click', () => {
            console.log('Clique no elemento!');
        });
    }
}
Enter fullscreen mode Exit fullscreen mode

Event Binding (Angular)

Essa é a forma mais comum de lidar com eventos no Angular. Utilizando a sintaxe () no template, associamos eventos HTML diretamente a métodos do componente, facilitando a interação entre a view e a lógica do componente.

Copy code
@Component({
    template: `<button (click)="onButtonClick()">click</button>`,
})
export class EventBindingComponent {
    onButtonClick(): void {
        console.log('Clique no elemento!');
    }
}
Enter fullscreen mode Exit fullscreen mode

Listen com Renderer2 (Angular)

O Renderer2 é uma API do Angular para manipulação da árvore de DOM de forma segura e em múltiplas plataformas (Web Browser, Web Worker ou Server-Side Rendering - SSR). Usando o método listen do Renderer2, é possível ouvir eventos em elementos.

@Component({
    template: `<button #el>click</button>`,
})
export class MyComponent implements OnInit, OnDestroy {
    el = viewChild.required<ElementRef>('el');
    renderer2 = inject(Renderer2);
    unlistener!: () => void;

    ngOnInit(): void {
        this.unlistener = this.renderer2.listen(this.el().nativeElement, 'click', () => {
            console.log('Clique no elemento!');
        });
    }

    ngOnDestroy(): void {
        this.unlistener();
    }
}
Enter fullscreen mode Exit fullscreen mode

O Renderer2 é uma ótima opção para aplicações em plataformas não web ou SSR, além de ser útil para adicionar eventos em elementos globais como "window", "document" e "body". Para aplicações SSR, o Angular lida com a verificação desses elementos.

HostListener (Angular)

Diferente dos outros exemplos, o HostListener é um decorator que escuta eventos no host do componente e executa a lógica de uma função toda vez que o evento é disparado. O HostListener ouve os eventos no próprio elemento que contém o componente, e não nos seus elementos filhos.

import { HostListener } from '@angular/core';

@Component({...})
export class MyComponent {
    @HostListener('click')
    click(): void {
        console.log('Clique no host!');
    }
}
Enter fullscreen mode Exit fullscreen mode

O HostListener está perfeitamente integrado ao ciclo de vida dos componentes do Angular, permitindo uma declaração simples no código, sem gerar boilerplate. É ideal para capturar eventos no host do componente.

Output (Angular)

A função output é utilizada para emitir eventos do componente filho para o componente pai. Essa abordagem é muito útil para a comunicação entre componentes.

import { Component, output } from "@angular/core";

@Component({
    selector: 'componente-filho',
    standalone: true,
    template: `<button (click)="buttonClick()">click</button>`,
})
export class FilhoComponent {
    onButtonClick = output<string>();

    buttonClick(): void {
        this.onButtonClick.emit('click');
    }
}

@Component({
    selector: 'componente-pai',
    standalone: true,
    imports: [FilhoComponent],
    template: `<componente-filho (onButtonClick)="onChildButtonClick($event)" />`,
    styles: ``
})
export class PaiComponent {
    onChildButtonClick($event: string): void {
        console.log('Clique no elemento do componente filho!', $event);
    }
}
Enter fullscreen mode Exit fullscreen mode

fromEvent (RxJs)

O fromEvent do RxJs é uma maneira reativa e assíncrona de criar eventos, transformando-os em Observables. Essa abordagem facilita a composição e manipulação de eventos, permitindo o uso dos operators do RxJs.

import { fromEvent } from 'rxjs';

@Component({
    template: `<button #el>click</button>`,
})
export class MyComponent implements OnInit, OnDestroy {
    el = viewChild.required<ElementRef>('el');
    subscription = Subscription.EMPTY;

    ngOnInit(): void {
        const evento = fromEvent(this.el().nativeElement, 'click');
        this.subscription.add(
            evento.subscribe(() => {
                console.log('Clique no elemento!');
            })
        );
    }

    ngOnDestroy(): void {
        this.subscription.unsubscribe();
    }
}
Enter fullscreen mode Exit fullscreen mode

Essa abordagem é extremamente poderosa para cenários de reatividade, pois você tem controle total sobre os fluxos de eventos, podendo utilizar operadores como take, delay, entre outros. Veja um exemplo simples:

fromEvent(window, 'click')
    .pipe(take(1), delay(1000))
    .subscribe(() => {
        console.log('Clique na janela!');
    });
Enter fullscreen mode Exit fullscreen mode

Nesse exemplo, o evento de click acontece apenas uma vez e após 1 segundo de ser disparado.

Conclusão

O Angular oferece diversas maneiras de lidar com eventos, permitindo flexibilidade conforme as necessidades da aplicação. O uso de addEventListener é mais direto e familiar para quem vem do JavaScript. O fromEvent traz os benefícios da programação reativa, ideal para cenários complexos e assíncronos. O Renderer2 oferece compatibilidade com múltiplas plataformas, ideal para aplicações SSR.

A escolha da abordagem correta depende dos requisitos específicos da aplicação, como a necessidade de manipulação de eventos em várias plataformas ou o uso de programação reativa.

Top comments (0)