Rota Angular Resolve em 10 Minutos

Atualizado em 13/07/2018: Revisão extensiva do código para usar convenções mais recentes. Atualização do Angular e do RxJS para as últimas versões disponíveis, moveu exemplos para o StackBlitz.

O objetivo deste post é demonstrar como a rota Angular resolve o trabalho em 10 minutos, juntamente com o fornecimento de código de exemplo no Stackblitz. Se você já está familiarizado com resolução de rotas do AngularJS, eu recomendo pular a introdução e pular direto para a seção de amostra do aplicativo.

Tabela de conteúdos

Intro
Aplicativo de amostra

  • Passo 1: Criar uma classe de resolução
  • Passo 2: Adicionar um Resolve Guard à rota
  • Passo 3: Obter os dados resolvidos da Rota Ativada do Componente

Notas & Dicas

  • Anular Chamadas API Redundantes
  • Múltiplas Resoluções em a mesma rota
  • Passar a rota Params para o Resolver

Closing Notes

Intro

Route resolve nada mais são do que uma forma de pré-buscar os dados que um componente precisa antes de ser inicializado. Normalmente estes dados vêm de uma API. Digamos que você tenha um componente cuja única função é exibir um gráfico de vendas diárias para o mês; não há sentido em renderizar a visão ou carregar esse componente antes que os dados de vendas estejam disponíveis. Na verdade, muitas bibliotecas de gráficos irão lançar um erro se você tentar inicializar um gráfico antes de fornecê-lo com dados (e assim será *ngFor). Claro, você pode facilmente contornar este problema escondendo o html com um *ngIf ou fornecendo temporariamente um array vazio até que os dados necessários sejam carregados. No entanto, enquanto você pode passar sem resolver, implementá-los ajuda a tornar o código mais legível e manejável por:

  1. Eliminar a confusão no template e código do seu componente.
  2. Clarificando sua intenção mostrando quais dados devem ser pré-passados.

Embora estes benefícios, muitos sites evitam usar resoluções a favor da exibição da maioria do componente e mostrar um spinner nas seções para as quais os dados ainda estão sendo carregados. Em alguns casos, esta abordagem é desejável do ponto de vista do UX, e uma resolução não deve ser usada. Use o seu critério.

Aplicação de Amostragem

Aplicação de Amostra Aberta

Como pode ver, o nosso ponto de partida é uma aplicação muito básica com duas rotas – “Home” e “News”. Você navega entre as rotas, clicando na guia correspondente. Nós vamos adicionar uma resolução para buscar notícias de uma API antes do carregamento dos componentes News. Isto tomará três passos:

Passo 1: Crie uma classe resolver que faça uma chamada Http para pré-viagem dos dados que precisamos.

Criar um novo ficheiro Typescript dentro da pasta app e nomeá-lo:

news-resolver.service.ts

Então copie e cole o seguinte código no seu novo ficheiro (explicado abaixo):

Dividamos o que fizemos no código acima:

  • Adicionar declarações de importação ES6 para trazer os módulos necessários.

  • Criado um novo TypeScript NewsResolver class.

  • Adicionado a interface Resolve à nossa classe – isto é OPCIONAL, mas qualquer classe que pretendemos usar como resolvedor deve implementar um método resolve, por isso é uma boa convenção.

  • Adicionado um método resolve() a NewsResolver – este é o método responsável por retornar os dados que precisamos. Nomear o método que retorna os dados para um resolved guard “resolve” NÃO é opcional – o resolvedor não funcionaria se o método fosse nomeado com outro nome.

  • Se você notou que um pedido POST está sendo usado incorretamente ao invés de um pedido GET no código acima, você está absolutamente certo; Em um aplicativo real, este seria um pedido GET. Os exemplos aqui aproveitam o , que é um site que fornece endpoints de API de teste.

Antes de continuar, devemos incluir a classe resolvedor que acabamos de criar em nosso módulo de roteamento. Navegue até app-routing.module.ts e adicione NewsResolver ao array providers. Ou, se você está apenas começando a trabalhar com Angular 2, simplesmente substitua o conteúdo de app-routing.module.ts pelo código abaixo – as mudanças são marcadas com notas:

Com isso feito, definimos agora a classe resolucionador. Nos passos seguintes, vamos adicioná-la à nossa rota.

Código Após Adicionar a Classe Resolver

Passo 2: Adicionar um Resolver Guard à rota.

Em app-routing.module.ts, altere a seguinte linha de código { path: 'news', component: NewsComponent } para:

{ path: 'news', component: NewsComponent, resolve: { news: NewsResolver }}

Tudo o que fizemos aqui foi adicionar o Resolver Guard que acabamos de definir à nossa rota news. Isto diz à Angular que devemos esperar pelo método NewsResolver‘s resolve() para retornar dados antes de exibirmos o método NewsComponent.

É importante ressaltar que news na linha news: NewsResolver do código é o que escolhi para nomear quaisquer dados retornados pelo resolvedor. Você pode nomear o que quiser.

Como um pouco de nota tangencial – se você não está familiarizado com guardas de rotas angulares em geral, e gostaria de saber mais, a documentação está aqui. Entrar em detalhes sobre guardas está fora do escopo deste post, mas você deve saber que existem outros guardas além de resolve disponíveis, e é por isso que eu trouxe o termo.

Code With The Resolve Guard Added

Passo 3: Obtenha os dados resolvidos da rota ativada do componente.

Agora temos uma classe resolved e adicionamos à nossa rota, os dados estão sendo pré-passados. O passo final é acessar os dados pré-aprovados no nosso NewsComponent localizado em app/news.component.ts. Navegue até esse arquivo e adicione o seguinte módulo ES6:

>

import { ActivatedRoute } from '@angular/router';

>

então forneça ActivatedRoute no construtor do componente News adicionando o seguinte código no topo da definição da classe NewsComponent:

>constructor(private route: ActivatedRoute) {}

Como você sabe, ou pode ter adivinhado, ActivatedRoute permite-nos aceder à informação sobre a rota que está actualmente activa, como a url da rota, parâmetros de consulta, etc. O que nos interessa aqui são os dados de notícias que são carregados no ActivatedRoute do resolved guard. Para obter os dados de notícias resolvidos da rota, adicione uma propriedade para guardar os dados de notícias:

public news: any;

e depois obtenha os dados da rota ativada quando a NewsComponent for inicializada:

 ngOnInit(): void { this.news = this.route.snapshot.data; }

É praticamente isso. Altere o modelo do componente de notícias para exibir as notícias da resolução da rota, removendo o conteúdo atual:

<div>This is just a placeholder for now. News will go here. </div>

e substituindo-as por:

>

Você deve agora ser saudado com as últimas notícias, “O céu está azul”, quando você clica na guia Notícias.

Código finalizado

Notas & Dicas

– As resoluções podem causar chamadas API redundantes: Uma resolução obtém dados cada vez que um componente é carregado. Isso geralmente resulta em chamadas de API desnecessárias que afetam negativamente o desempenho. Se seu resolved recebe dados que não mudam com freqüência, considere escrever os dados retornados pelo resolvedor em uma propriedade da classe resolucionadora e simplesmente retornar essa propriedade se ela já tiver sido definida. Por exemplo, em nosso exemplo, adicionaríamos uma propriedade inicialmente indefinida news como esta: public news: any = undefined; no nosso resolvedor de notícias. Então, no método resolve(), verifique se a propriedade news já está definida e retorne seu valor sem fazer uma chamada API se estiver, ou seja:

 resolve(): Observable<any> { if (this.news) { return this.getSavedNews(); } else { return this.getNewsFromApi() } }

Código completo exemplo abaixo. Se a sintaxe observável parece um pouco incomum para você, é porque estou usando RxJS 6. Há um bom tutorial sobre as alterações recentemente introduzidas em RxJS aqui se você precisar de um refresh.

Retornar Dados Salvos, se já foi obtido da API

Naturalmente, você poderia ir mais longe e definir um período de tempo durante o qual os dados são válidos, não apenas salvando os dados, mas adicionando outra propriedade de timestamp e fazendo uma chamada da API se os dados forem mais antigos que x.

– Assim como em AngularJS, você pode usar várias resoluções na mesma rota. As chamadas de resolução são feitas em paralelo e o componente será carregado somente depois que todas as chamadas retornarem dados. Para usar múltiplas resoluções, simplesmente adicione-as à rota:

– Então dados adicionais de resolução podem ser acessados a partir do instantâneo da rota como uma única resolução:

 ngOnInit(): void { this.news = this.route.snapshot.data; this.alternativeNews = this.route.snapshot.data; }

Code With Multiple Resolves

– O resolvedor tem acesso aos parâmetros da rota. Digamos que você tem um componente que exibe uma lista de títulos de notícias. Quando uma história é clicada, outro componente, que mostra o artigo completo, é aberto. Antes de carregar esse componente, precisamos pré-passar o conteúdo da notícia cujo título foi clicado – isso pode ser feito no método de resolução. A classe resolver tem acesso a ActivatedRoute, assim podemos obter o id da história que foi clicada:

 resolve(route: ActivatedRouteSnapshot) { let id: any = route.params); return this.getNewsStory(id); }

Isto é bastante auto-explicativo. Para um exemplo, veja o novo arquivo src/news-story-resolver.service.ts no link abaixo. Os links para o novo componente foram adicionados na aba News (news.component.ts).

Code With Parameterized Resolve

Deixe uma resposta

O seu endereço de email não será publicado.