Introdução
Imagine uma situação em que você está construindo um novo recurso no front-end de um aplicativo, mas os endpoints HTTP disponíveis ainda não estão prontos para serem consumidos pela equipe de desenvolvimento de back-end. Este é um problema comum ao trabalhar dentro de uma grande equipe de vários tipos de desenvolvedores. Para superar esse obstáculo durante o desenvolvimento, podemos usar um servidor falso para imitar todas as operações CRUD de uma API HTTP REST enquanto nossos dados residem localmente em nosso aplicativo front-end.
Neste tutorial, vamos explorar o Angular-in-memory-web-api, seguido por um desenvolvimento prático de um servidor falso para simular um back-end CRUD simples no Angular, para que você possa construir um funcional front-end sem depender da equipe de back-end.
Pré-requisitos
Antes de começarmos, certifique-se de ter o seguinte para acompanhar este tutorial:
- Node.js V10.x
- Conhecimento prévio de trabalho do Angular
- Conhecimento prévio de trabalho em TypeScript
Apresentando o Angular-in-memory-web-api
Angular-in-memory-web-api
é uma biblioteca que intercepta solicitações Http
e HttpClient
angulares que, de outra forma, iriam para o remoto servidor e os redireciona para um armazenamento de dados na memória que você controla no front-end. Com esta biblioteca, você pode imitar perfeitamente as respostas atrasadas e fazer basicamente tudo o que pode ser necessário de um desenvolvedor de back-end. No entanto, ele tem recursos limitados e não se destina ao uso em produção.
Configurando um projeto Angular
Neste tutorial, usaremos a ferramenta angular CLI para estruturar nosso projeto.
Para verificar se você tem a ferramenta Angular CLI já instalada, execute o seguinte comando em seu terminal:
ng--version //ou ng v
Instale a ferramenta angular CLI com o seguinte comando:
npm install-g @ angular/cli @ 10.0.0
Agora podemos criar um novo projeto Angular com o seguinte comando:
ng novo angular-api-backend
O Angular CLI solicitará alguns detalhes sobre o aplicativo que você deseja criar para que possa dar suporte ao projeto Angular.
Inicialmente, ele perguntará se você gostaria de adicionar o roteamento Angular. Para este tutorial, responda “Não” à pergunta e pressione Enter.
A próxima pergunta é sobre qual formato de folha de estilo você gostaria de usar. Aceite a escolha padrão (CSS) e pressione Enter.
Este processo pode demorar algum tempo, dependendo da sua conexão com a internet. Durante esse tempo, o Angular CLI baixará e instalará todas as dependências necessárias, bem como criará arquivos padrão para seu aplicativo Angular.
Quando terminar, ele terá criado uma pasta chamada angular-api-backend
. Navegue até a pasta recém-criada e inicie seu aplicativo com o seguinte comando:
ng servir
O Angular CLI compila nosso projeto Angular recém-criado e inicia um servidor da web que observa as alterações nos arquivos do projeto.
Configurando o angular-in-memory-web-api
A Angular-in-memory-web-api
é muito fácil de instalar e configurar.
Etapa um
Primeiro, precisamos instalar o angular-in-memory-web-api
como uma dependência de desenvolvimento, pois o usaremos apenas para desenvolvimento:
npm install angular-in-memory-web-api--save-dev
No diretório src/app
, crie o arquivo data.services.ts
e adicione o seguinte:
//src/app/data.services.ts importar {injetável} de'@ angular/core'; importar {InMemoryDbService} de'angular-in-memory-web-api'; @Injectable ({ fornecido em:'root' }) export class DataService implementa InMemoryDbService { construtor () {} createDb () { Retorna { produtos: [ { id: 1, nome:'Seaman Cap', descrição:'Lorem ipsum. Voluptatem excepturi magnam nostrum dolore recusandae', preço:'$ 40' }, { id: 2, nome:'T-shirt', descrição:'amet consectetur adipisicing elit.Lorem ipsum dolor sit', preço:'$ 80' }, { id: 3, nome:'Back Pack', descrição:'Voluptatem excepturi harum rerum aliquam magnam nostrum dolore recusandae', preço:'$ 30' } ] }; } }
O trecho de código acima é um serviço Angular real que implementa a interface InMemoryDbService
. O serviço Angular então implementa o método createDb
da interface InMemoryDbService
, que cria um objeto na memória que representa nosso banco de dados. Cada chave no objeto representa uma entidade de nosso banco de dados, como produtos
.
Etapa dois
Adicione o seguinte a src/app/app.module.ts
:
//src/app/app.module.ts importar {HttpClientInMemoryWebApiModule} de'angular-in-memory-web-api'; importar {DataService} de'./data.service'; @NgModule ({ ... importações: [ ... HttpClientInMemoryWebApiModule.forRoot (DataService), ], ... })
Observe como importamos HttpClientInMemoryWebApiModule
chamando seu método forRoot
, passando o DataService
como parâmetro. Fizemos isso para evitar a criação de várias instâncias de DataService
.
Criamos com sucesso uma API de back-end para nosso aplicativo Angular sem configurar uma infraestrutura de servidor de back-end real.
Apresentando o cliente HTTP Angular
O cliente Angular http é um cliente HTTP integrado da estrutura Angular. Este serviço está disponível como uma classe injetável, com métodos para realizar solicitações HTTP. Ele é instalado pelo Angular CLI por padrão ao criar um novo projeto Angular.
Para usá-lo, precisamos adicionar o seguinte a src/app/app.module.ts
:
//src/app/app.module.ts importar {HttpClientModule} de'@ angular/common/http'; @NgModule ({ ... importações: [ ... HttpClientModule, ] })
As instâncias do serviço HttpClientModule
têm acesso a uma variedade de métodos para realizar operações de solicitação comuns, como GET
, POST
,
Lidando com operações CRUD em Angular
Criar aplicativos CRUD é uma das melhores abordagens para aprender novas ferramentas e conceitos no desenvolvimento de software.
Para entender melhor como simular APIs CRUD no Angular, construiremos um aplicativo CRUD de demonstração que cria produtos, atualiza e os exclui.
Organizaremos nosso código em módulos, pois criaremos o módulo produtos
da seguinte maneira:
ng gerar produtos de módulo
A seguir, vamos registrar um componente lista de produtos
com o módulo produtos
:
ng gerar produtos de componentes/productList--module=produtos
Adicione os seguintes estilos CSS a products/product-list/productlist.component.css
:
//products/product-list/productlist.component.css #clientes { família da fonte: Arial, Helvetica, sans-serif; colapso da fronteira: colapso; largura: 100%; } #customers td, #customers th { borda: 1px sólido #ddd; preenchimento: 8px; } #customers tr: nth-child (even) {background-color: # f2f2f2;} #customers tr: hover {background-color: #ddd;} #customers th { acolchoamento superior: 12px; acolchoamento inferior: 12px; alinhamento de texto: esquerda; cor de fundo: # 4CAF50; cor branca; }
Interface do produto
Navegue até o diretório produtos
e crie product.model.ts
com o seguinte:
//products/product.model.ts interface de exportação do produto { número de identidade; nome: string; }
Aqui, criamos uma interface de tipo para a estrutura dos dados do produto com os quais trabalharemos.
Comunicação com o back-end da API
Para nos comunicarmos com o back-end, precisamos injetar o HttpClient
em nosso ProductService
para que tenhamos acesso ao GET
, POST
, PUT
e todos os outros verbos HTTP necessários para enviar uma solicitação HTTP ao back-end.
No diretório products
, crie um arquivo product.service.ts
e adicione o seguinte:
import {Injetável} de'@ angular/core'; importar {Product} de'./product.model'; importar {HttpClient, HttpErrorResponse} de'@ angular/common/http'; import {Observable, throwError} de'rxjs'; import {catchError, tente novamente} de'rxjs/operadores'; @Injectable ({ fornecido em:'root' }) export class ProductService { private productsUrl='api/products/'; construtor (privado http: HttpClient) {} getProducts (): Observável{ return this.http.get (this.productsUrl).pipe ( tentar novamente (2), catchError ((erro: HttpErrorResponse)=> { console.error (erro); return throwError (erro); }) ); } createProduct (product: Product): Observable { product.id=null; retornar this.http.post (this.productsUrl, produto).pipe ( catchError ((erro: HttpErrorResponse)=> { console.error (erro); return throwError (erro); }) ) } editProduct (product: Product): Observável { retornar this.http.put (this.productsUrl + product.id, product); } deleteProduct (id: número): Observável { retornar this.http.delete (this.productsUrl + id); } }
No snippet acima, importamos HttpClient
de um pacote HTTP integrado do Angular e o injetamos na classe ProductService
da seguinte maneira:
construtor (privado http: HttpClient) {}
O método getProducts
usa o serviço HttpClient
para obter a lista de produtos do banco de dados e retorna um Observable
deles. O método GET
de HttpClient
aceita a URL de um endpoint de API como um parâmetro.
Se você estiver familiarizado com o TypeScript, notará que usamos genéricos
no método GET
para obter uma resposta do tipo específico de dados retornou do servidor. Em nosso caso, uma matriz de objetos Product
.
A angular-inmemory-web-api
requer que o URL sempre comece com a palavra “api”, seguida pela entidade que queremos acessar:
private productsUrl='api/products/';
Em nosso caso, a entidade é produtos
, conforme definido anteriormente no método createDb
de DataService.
O método createProduct
usa o pós-verbo HttpClient
para fazer uma pós-solicitação para criar um novo produto no banco de dados. Ele retorna um Observable
do produto recém-criado.
O método editProduct
usa o HttpClient
para fazer uma solicitação PUT
para atualizar um produto existente no banco de dados. Como com createProduct
, ele retorna um Observable
do produto atualizado.
Finalmente, o método deleteProduct
usa o HttpClient
para fazer uma solicitação de exclusão para remover um produto existente do banco de dados. De forma semelhante, retorna um Observable
do produto excluído.
Agora, configuramos o HttpClient
em nosso ProductService
. A próxima etapa é fazer com que nosso componente assine o fluxo observável, porque os métodos do ProductService
retornam um fluxo observável em vez de dados brutos.
Assinatura de um fluxo observável de dados em componentes
Atualize product-list.component.ts
com o seguinte:
//products/product-list/productlist.component.ts import {Component, OnInit} de'@ angular/core'; importar {Product} de"../product.model" importe {ProductService} de"../product.service" @Componente({ seletor:'app-product-list', templateUrl:'./product-list.component.html', styleUrls: ['./product-list.component.css'] }) export class ProductListComponent implementa OnInit { product={ nome:'', id: null } editar=verdadeiro; add=false; produtos: Produto []; construtor (productService privado: ProductService) {} ngOnInit (): void { this.getProducts () } private getProducts () { this.productService.getProducts (). subscribe (products=> this.products=products); } addProduct () { dados const={ nome: this.product.name, id: this.product.id }; this.productService.createProduct (dados).subscribe (resposta=> { console.log (resposta) this.getProducts (); }); } setProductEdit (produto: Produto) { this.product.name=product.name; this.product.id=product.id; this.edit=false; this.add=true; } resetValues () { this.product.name=""; this.product.id=null; this.edit=true; this.add=false; } removeProduct (produto: Produto) { const id=product.id; console.log (produto) this.productService.deleteProduct (id).subscribe (product=> console.log (product)); this.getProducts () } updateProduct () { this.productService.editProduct (this.product).subscribe (resposta=> console.log (resposta)); this.getProducts () this.resetValues () } }
O método getProducts
se inscreve no método getProducts
de ProductService
e define o resultado para a propriedade products
de o componente, enquanto o gancho do ciclo de vida ngOnInit ()
chama o método getProducts
quando o componente é inicializado.
Da mesma forma, os métodos addProduct
, removeProduct
e updateProduct
assinam respectivamente createProducts
, editProduct métodos
e deleteProduct
de ProductService
.
Agora, vamos acoplar a lógica do componente ao modelo.
Adicione o seguinte a products/product-list/productlist.component.html
:
//products/product-list/productlist.component.html
S/N | Nome | Atualização | Excluir |
---|---|---|---|
{{product.id}} | {{product.name}} |
A diretiva * ngFor
é usada para renderizar uma lista de itens com base em uma fonte de dados. Em nosso caso, renderizamos dados de um produto para cada um dos objetos de produto em nossa matriz de produtos.
Atualize products.module.ts
da seguinte maneira:
import {NgModule} de'@ angular/core'; import {CommonModule} de'@ angular/common'; importar {ProductListComponent} de'./product-list/product-list.component'; import {FormsModule, ReactiveFormsModule} de'@ angular/forms'; @NgModule ({ declarações: [ProductListComponent], importações: [ CommonModule, FormsModule, ReactiveFormsModule ], exportações: [ProductListComponent] }) export class ProductsModule {}
Agora, vamos renderizar nosso componente lista de produtos
no navegador.
Atualize app.component.html
da seguinte maneira:
Além disso, atualize app.module.ts
da seguinte maneira:
import {NgModule} de'@ angular/core'; importar {BrowserModule} de'@ angular/platform-browser'; importar {HttpClientModule} de'@ angular/common/http'; importar {AppComponent} de'./app.component'; importar {ProductsModule} de"./products/products.module" importar {HttpClientInMemoryWebApiModule} de'angular-in-memory-web-api'; importar {DataService} de'./data.service'; @NgModule ({ declarações: [ AppComponent, ], importações: [ BrowserModule, HttpClientModule, ProductsModule, HttpClientInMemoryWebApiModule.forRoot (DataService) ], provedores: [], bootstrap: [AppComponent] }) exportar classe AppModule {}
Tem sido uma longa construção, então vamos ver nosso projeto final no navegador. Se seu servidor de desenvolvimento estiver desligado, execute o comando ng serve
novamente e abra seu navegador em http://localhost: 4200/.
Conclusão
Neste tutorial, criamos um aplicativo CRUD básico que usa o pacote angular-in-memory-web-api
para simular uma API REST com um banco de dados na memória para quando os endpoints HTTP ainda não estão prontos para serem consumidos pela equipe de desenvolvimento de back-end.
Se estiver interessado, você pode encontrar o repositório github para nosso aplicativo CRUD aqui.
A postagem Angular-in-memory-web-api tutorial: mocking CRUD APIs no Angular apareceu primeiro no LogRocket Blog .