O objetivo deste artigo é mostrar como podemos construir um mecanismo para emitir notificações ao usuário.
Este mecanismo será composto por uma service e um componente. A ideia é que a service tenha a propriedade providedIn com o valor root em seu decorator para que haja uma única instância em toda a aplicação. Isso facilita bastante visto que a aplicação toda terá acesso a este única instancia que fará a ponte entre a aplicação toda e o componente de notificação.
Já o componente, que chamaremos de app-notificacoes, será referenciado dentro do template do app.component.html para que as notificações apareçam em todas as telas, visto que nosso <router-outlet> está neste template (app-component.html).
Construção da Service
Aqui não tem muito segredo, vamos estruturar a service da seguinte forma:
O esqueleto da service está logo acima mas antes de "rechearmos" os métodos, vamos comentar um pouco sobre o Subject<NotificacaoAcao>.
O Subject nos permite emitir valores, que no nosso caso será um objeto do tipo NotificacaoAcao, e quem efetuar uma subscrição (subscribe) irá "ouvir/receber" estes valores. É mais ou menos quando você liga uma rádio no seu carro, a partir do momento que você sintonizou ("subscrição") a estação você passa a receber o audio.
A princípio quem irá "ouvir" estes valores emitidos será o app-notificacoes que será construído mais a frente. Por enquanto vamos finalizar a construção da service e na sequência comentamos sobre os tipos Notificacao e NotificacaoAcao:
Veja nos métodos acima que estamos emitindo alguns valores através do this.notificacoes.next(...). A ideia é que o nosso componente, que será construído a seguir, receba estas informações e renderize na tela as mensagens de notificação.
Repare que há uma propriedade chamada acao, que será interpretada pelo componente app-notificacoes que veremos mais a frente.
O timer() utilizado dentro do método notificar() é como um setTimeout, ele emite um valor no subscribe sempre que o tempo passado como parâmetro é esgotado, por exemplo:
console.log('teste');
timer(3000).subscribe(() => {
console.log('Se passaram 3 segundos após o último console.log');
});
Utilizamos este recurso para as notificações que tem tempo de vida, ou seja, podemos emitir uma notificação já configurada para desaparecer após x segundos.
Construção do componente app-notificacoes
Primeiramente vamos criar dois type, um para representar o objeto de notificação e outro para representar uma ação:
Veja que teremos 3 possíveis cenários com o NotificacaoAcao:
incluir uma nova notificação: { acao: 'novo' }
remover uma notificação específica: { acao: 'remover' }
remover todas as notificações: { acao: 'remover-todas' }
Estas 3 opções serão interpretadas dentro do componente app-notificacoes.
Agora focando no código do componente, temos que injetar a instância da service NotificacosService no constructor, efetuar um subscribe no observable que emite as notificações da service e desenvolver a lógica para os três casos citados logo acima.
O código do componente ficará da seguinte forma:
Veja que temos uma variável notificacoes: Notificacoes[] que utilizaremos como referência para renderizar as notificações no template.
O restante do código é apenas para gerenciar o conteúdo deste array a partir das mensagens que chegam no observable da service NotificacoesService.
Código do template e na sequência do CSS:
Testando as notificações
Agora com o componente pronto, vamos referenciá-lo no app.component.html e adicionar alguns pontos de teste conforme o código abaixo:
Para aproveitarmos este código e irmos um pouco além do objetivo deste artigo, vamos incrementar um pouco e mostrar no app.component.html a quantidade de notificações na tela. Para isto vamos incluir um novo Subject<number> e deixar o app-notificacoes "avisar" a NotificacoesService sobre a quantidade de visiveis notificações na tela:
Finalmente no AppComponent:
Veja que ao invés de efetuarmos um subscribe explicíto no getNotificacoesLength(), estamos utilizando um | async para fazer este trabalho. O código fica bem mais limpo desta forma.
O resultado final:
Considerações
Este artigo apresenta uma forma bem legal de se compartilhar dados entre componentes com a utilização de services com o providedIn: 'root'. Vale lembrar que existem outros métodos para isto e também para construir este esquema de notificação.
Podemos utilizar este recurso do Subject para por exemplo "avisar" a aplicação toda que o usuário efetuou o login ou alterou algo em algum lugar que poderá refletir em outro.