.Net + Angular + PoUi : FullStackPlayGroung
Tags: angular, dotnet, poui
Published: 2021-06-17 01:15:29

Oi Pessoal!

Nesse post vou mostrar como criar um crud com .net e angular utilizando [po-ui](https://po-ui.io/), uma biblioteca de componentes para angular de alta produtividade.

Faça o clone ou download do código.
{% github silverio27/FullStackPlayGround no-readme %}


## Você precisa ter instalado em sua máquia:
- [.Net5 SDK](https://dotnet.microsoft.com/download/dotnet/5.0)
- [VsCode](https://code.visualstudio.com/)
- [Windows Terminal](https://www.microsoft.com/pt-br/p/windows-terminal/9n0dx20hk701)
- [NodeJs](https://nodejs.org/en/download/)
- [Angular - CLI](https://angular.io/cli)

Abra uma pasta de sua preferencia no terminal.
Crie uma pasta chamada **src**.
Criaremos os projetos dentro desta pasta.

Abra o terminal e navegue até esta pasta e digite o comando abaixo para abrir o vscode.

```CMD
code .
```

A partir de agora vamos utilizar o terminal integrado do vscode. Aperte ctrl + ' para abrir o terminal integrado.


## BackEnd
### WebApi

Crie o projeto com o comando abaixo:

```CMD
dotnet new webapi -o api
```

> Apague as classes **WeatherForecast.cs** e **Controllers/WeatherForecastController.cs**

Navegue até a pasta do projeto

```CMD
cd api
```

Crie um arquivo de gitignore
```CMD
dotnet new gitignore
```

Crie a pasta **Models** e crie a classe **Pet**:

```CMD
md Models
cd . > Models/Pet.cs
```
No menu lateral do vscode procure a pasta Models e abra a classe Pet.cs

A classe Pet.cs deve ter o seguinte código:

```C#
namespace api.Models
{
    public class Pet
    {
        public int Id { get; set; }
        public string Nome { get; set; }
        public string Raca { get; set; }
        public string Dono { get; set; }
    }
}
```

Instale o pacote Microsoft.EntityFrameworkCore.InMemory
> Esse pacote é para utilizarmos um banco de dados em memória, ideal para testes.

```CMD
dotnet add package Microsoft.EntityFrameworkCore.InMemory --version 5.0.7
```

Crie a pasta **Data** e crie a classe **DataContext**:

```CMD
md Data
cd . > Data/DataContext.cs
```

A classe DataContext.cs deve ter o seguinte código:

```C#
using api.Models;
using Microsoft.EntityFrameworkCore;

namespace api.Data
{
    public class DataContext : DbContext
    {
        public DataContext(DbContextOptions<DataContext> options)
            : base(options) { }
        public DbSet<Pet> Pet { get; set; }
    }
}
```

Adicione as referências abaixo no topo da classe Startup.cs:

```C#
using api.Data;
using Microsoft.EntityFrameworkCore;
```

Adicione o trecho abaixo no método ConfigureServices na classe Startup.cs

```C#
public void ConfigureServices(IServiceCollection services)

    services.AddControllers();
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "api", Version = "v1" });
    })

    //adicione este trecho
    services.AddDbContext<DataContext>(opt => opt.UseInMemoryDatabase("DataBase"));
}
```

Instale a ferramenta de geração de código

```CMD
dotnet tool install -g dotnet-aspnet-codegenerator
```
ou atualize caso ela já esteja instalada
```CMD
dotnet tool update -g dotnet-aspnet-codegenerator
```

Adicione os pacotes abaixo para gerar a nossa api rest automaticamente.

```CMD
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
```

Gere o scaffolding do model Pet.cs
```CMD
dotnet aspnet-codegenerator controller -name PetController -async -api -m Pet -dc DataContext -outDir Controllers
```

Observe o código criado em Controllers/PetController.cs, foi criada uma operação de crud completo.

Execute o código abaixo para rodar a aplicação.
```CMD
dotnet run
```

Instale a extensão do vscode, Thunder Client ou utilize o postman para testar.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4idcc20ou0xbsmp33f1u.png)
 

Utilize o endpoint https://localhost:5001/api/pet e alterne os métodos GET (obter)/POST (criar)/PUT (atualizar)/DELETE (deletar)

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5x41edmim1j1y9h6evcu.png)
 
Para encerrar o aplicativo, aperte ctrl + c no terminal.

Para permitir os teste do endpoint no aplicativo angular temos q liberar o cors. Em Startup.cs altere o método Configure:

```C#
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseSwagger();
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "api v1"));
            }

            // Comente esse trecho
            // app.UseHttpsRedirection();

            app.UseRouting();
            
            // adicione esse trecho
            app.UseCors(x => x
                .AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader());

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
```

Refatore o método GetPet em Controllers/PetController.cs para compatibilidade com o contrato de api do po-ui: https://po-ui.io/guides/api#successMessagesForCollections

```C#
...
        [HttpGet]
        public async Task<ActionResult<dynamic>> GetPet()
        {
            var pets =  await _context.Pet.ToListAsync();
            
            return new {
                hasNext = false,
                items = pets
            };
        }
...
```

Nosso back-end está pronto!

## Front-End

### WebApp

Volte a raiz do projeto, a pasta **src**.

> Esse projeto utiliza a versão Angular CLI: 12.0.1

Crie o projeto com o comando abaixo:

```CMD
ng new app
```

Diga sim para a pergunta sobre criação de rota e escolha CSS como linguagem de estilo

Navegue até a pasta do aplicativo.

```CMD
cd app
```

Adicione o pacote de ui do Po-UI

```CMD
ng add @po-ui/ng-components
```

Diga sim para criação do procedimento e para criação de menu lateral

Adicione o pacote de template do PO-UI

```CMD
ng add @po-ui/ng-templates
```

### Componentes

crie o componente de leitura de dados

```CMD
ng generate @po-ui/ng-templates:po-page-dynamic-table
```

quando perguntado, informe o nome **PetTable**

crie o componente de edição de dados

```CMD
ng generate @po-ui/ng-templates:po-page-dynamic-edit
```

quando perguntado, informe o nome **PetEdit**

### Rotas

Utilize o menu lateral do vscode e encontre o arquivo app/src/app/app-routing.module.ts

adicione os imports no topo do arquivo:

```TS
...
import { PetEditComponent } from './pet-edit/pet-edit.component';
import { PetTableComponent } from './pet-table/pet-table.component';
...
```

No mesmo arquivo adicione as rotas:

```TS
...
const routes: Routes = [
  { path: 'new', component: PetEditComponent },
  { path: 'edit/:id', component: PetEditComponent },
  { path: 'table', component: PetTableComponent },
  { path: '', pathMatch: 'full', redirectTo: 'table' },
];
...
```

altere o código de app/src/app/app.component.html para adicionar elemento router-outlet (para dar suporte as rotas) e o título do aplicativo

```HTML
<div class="po-wrapper">
  <po-toolbar p-title="Pet App"></po-toolbar>

  <po-menu [p-menus]="menus"></po-menu>

  <router-outlet></router-outlet>
</div>

```

altere o código de app.component.ts para remover o código desnecessário e acrescentar a rota para tabela de pets no menu.

```TS
import { Component } from "@angular/core";

import { PoMenuItem } from "@po-ui/ng-components";

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"],
})
export class AppComponent {
  readonly menus: Array<PoMenuItem> = [{ label: "Pets", link: "/table" }];
}
```
### Services

adicione a propriedade service em app/src/environments/environment.ts

```TS
export const environment = {
  production: false,
  service: 'http://localhost:5000/api/pet'
};
```

altere o endpoint e as propriedades em app/src/app/pet-table/pet-table.component.ts

```TS
...
// adicione esses imports
import { PoPageDynamicTableActions, PoPageDynamicTableField } from '@po-ui/ng-templates';
import { environment } from 'src/environments/environment';

@Component({
  selector: 'app-pet-table',
  templateUrl: './pet-table.component.html',
  styleUrls: ['./pet-table.component.css']
})
export class PetTableComponent implements OnInit {

  // Copie os códigos abaixo
  readonly apiService = environment.service;


  readonly actions: PoPageDynamicTableActions = {
    new: "/new",
    edit: "/edit/:id",
    remove: true,
  };

  readonly fields: Array<PoPageDynamicTableField> = [
    { property: "id", label: "Id", key: true },
    { property: "nome", label: "Nome" },
    { property: "raca", label: "Raça" },
    { property: "dono", label: "Dono" },
  ];
  ...
```

adicione a propriedade p-fields em app/src/app/pet-table/pet-table.component.html

```HTML
<po-page-dynamic-table
  p-title="PetTable"
  [p-actions]="actions"
  [p-service-api]="apiService"
  [p-fields]="fields">
</po-page-dynamic-table>

```

e em app/src/app/pet-edit/pet-edit.component.ts

```TS
...
// adicione esses imports
import { PoPageDynamicEditActions, PoPageDynamicEditField } from '@po-ui/ng-templates';
import { environment } from 'src/environments/environment';

@Component({
  selector: 'app-pet-edit',
  templateUrl: './pet-edit.component.html',
  styleUrls: ['./pet-edit.component.css']
})
export class PetEditComponent implements OnInit {

  // copie os códigos abaixo
  readonly apiService = environment.service;

  readonly fields: Array<PoPageDynamicEditField> = [
    { property: "id", label: "Id", key: true, visible: false },
    { property: "nome", label: "Nome" },
    { property: "raca", label: "Raça" },
    { property: "dono", label: "Dono" },
  ];

  public readonly actions: PoPageDynamicEditActions = {
    save: "/table",
    saveNew: "/new",
  };
...
```

adicione a propriedade p-actions em app/src/app/pet-edit/**pet-edit.component.html**

```HTML
<po-page-dynamic-edit
  p-title="PetEdit"
  [p-service-api]="apiService"
  [p-fields]="fields"
  [p-actions]="actions">
</po-page-dynamic-edit>
```

Pronto nosso front-end está pronto!

Para executar os dois projeto, crie uma nova aba do terminal e navegue até ..src/api e execute
```CMD
dotnet run
```
em outra aba do terminal navegue até ..src/app e execute:
```CMD
ng s -o
```
Eu utilizei o próprio terminal integrado com duas instancias:
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q8hg921d1tq9jprghw8n.png)

Agora vamos testar!
### Testes
No navegador foi aberto a página: http://localhost:4200/table

Veja toda estrutura que foi criada, isso é incrível!

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vox3p1vanmivlo40nox0.png)

Clique no botão novo e você será direcionado para a página com o formulário de edição:

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qhjbejpytdi0xdi4q3od.png)

Preencha o formulário e clique em salvar.

Você será redirecionado para página de tabela, repare que o dado foi incluído, listado e apareceu uma notificação de sucesso.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hpnqg2dp4zwensyqwh8m.png
)
  
 Agora vamos atualizar esse dado:

Clique nos 3 pontinho no final da linha e depois em editar:

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yt0ijm40ufncyuunsfvx.png)

Altere o nome do dono e clique em salvar:

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w82k42d1ycln2i928vj3.png)

Você será redirecionado para página de tabela novamente e o dado foi alterado e uma nova notificação foi adicionada.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qq6de5uomtkonpjsqm1l.png)


Agora vamos excluir o dado:

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lk0wy4rlixivl5frn2l8.png)

Uma janela de confirmação vai abrir, clique em confirmar:

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xtxzuw7x8iyq1gtzcbky.png)

Veja que o item já não aparece mais e uma notificação foi adicionada.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mv13lkjesgk0xlf22ul3.png)

O Post ficou um pouco grande, mas a replicação desse projeto é rápido.

O [PO-UI](https://po-ui.io/) é uma biblioteca fantástica!!!
Veja que criamos uma estrutura de crud, notificação e navegação de forma muito rápida e com pouco código! Confira todos os componentes no portal deles.

Espero que isso te ajude!