Modelo de Referência para Angular¶
O que é o Framework Angular¶
Angular ⧉ é um framework de desenvolvimento web amplamente utilizado, desenvolvido pela Google, que simplifica a criação de aplicativos web robustos e escaláveis. Baseado em JavaScript e TypeScript, o Angular fornece uma estrutura sólida para a construção de interfaces de usuário modernas e dinâmicas. Ele é caracterizado por seu alto desempenho, arquitetura modular e extensibilidade, o que o torna uma escolha ideal para empresas que buscam desenvolver aplicações corporativas de alto nível.
O Angular promove o desenvolvimento baseado em componentes ⧉, o que significa que você pode criar componentes reutilizáveis que agilizam o desenvolvimento e garantem consistência na interface do usuário em toda a aplicação e utiliza o TypeScript ⧉ como linguagem principal, o que oferece a vantagem de tipagem estática. Isso ajuda a evitar erros de programação, melhorando a qualidade do código e a segurança do aplicativo.
Além disso, a ferramenta possui uma vasta biblioteca de módulos e extensões que facilitam a integração com outras tecnologias e serviços, como autenticação, gráficos e gerenciamento de estado.
Versões/Releases aplicáveis¶
A Magna Sistemas, por meio do MITH (Magna Innovation Technology Hub), estabelece padrões para o desenvolvimento de projetos. Em projetos Angular, há semelhanças importantes que demandam planejamento cuidadoso, definição de metas claras e estratégias eficientes para obter resultados consistentes. Assim como uma empresa busca maximizar a eficiência e a colaboração de sua equipe, a padronização do uso de bibliotecas promove a coesão e a reutilização de código, aumentando a produtividade e a qualidade dos projetos. A adoção de uma biblioteca padrão oferece uma base sólida para o desenvolvimento, garantindo consistência, manutenibilidade e escalabilidade nos projetos.
Os arquitetos e líderes têm a liberdade de preferir outras bibliotecas relevantes, porém, é importante destacar que a padronização contribui para melhorar a performance e facilitar a colaboração entre as equipes
Guia do desenvolvedor¶
Como um framework, o Angular inclui uma coleção de bibliotecas integradas que cobrem uma ampla variedade de funcionalidades. As bibliotecas Angular incluem roteamento, gerenciamento de formulários, comunicação cliente-servidor e mais.
Estrutura de diretórios¶
├── dist # Diretório onde são gerados os arquivos finais de build da aplicação.
├── node_modules # Diretório onde ficam as dependências instaladas pelo npm ou yarn.
├── src # Diretório principal do código-fonte da aplicação.
│ └── app # Diretório da aplicação principal.
│ ├── core # Diretório que contém as funcionalidades e serviços base da aplicação.
│ │ ├── api # Diretório que contém a implementação de serviços de comunicação com APIs.
│ │ ├── services # Diretório que contém serviços de negócios usados em toda a aplicação.
│ ├── modules # Diretório que contém módulos (páginas) específicos da aplicação.
│ │ ├── admin # Ex.: Módulo administrativo.
│ │ │ ├── shared # Ex.: Diretório que contém componentes compartilhados para o módulo administrativo.
│ │ │ ├── admin.component.html # Ex.: Arquivo HTML do componente principal do módulo administrativo.
│ │ │ ├── admin.component.ts # Ex.: Arquivo Typescript do componente principal do módulo administrativo.
│ │ │ ├── admin.routes.ts # Ex.: Arquivo Typescript utilizado para a configuração das rotas do módulo administrativo.
│ │ │ ├── admin.service.ts # Ex.: Arquivo Typescript que contém as regras de negócio do módulo administrativo
│ │ ├── auth # Ex.: Módulo de autenticação.
│ │ └── landing # Ex.: Módulo da landing page.
│ ├── shared # Diretório que contém componentes e serviços compartilhados entre os módulos.
│ │ ├── components # Diretório que contém componentes compartilhados entre os módulos.
│ │ ├── icons # Diretório que contém um provider para busca de ícones usados na aplicação.
│ │ ├── layout # Diretório que contém componentes de layout compartilhados.
│ │ ├── models # Diretório que contém modelos de dados usados na aplicação.
│ │ ├── pipes # Diretório que contém pipes compartilhados entre os módulos.
│ │ ├── directives # Diretório que contém diretivas compartilhadas entre os módulos.
│ ├── app.component.html # Arquivo de template HTML do componente principal da aplicação.
│ ├── app.component.scss # Arquivo de estilos SCSS do componente principal da aplicação.
│ ├── app.component.ts # Arquivo TypeScript do componente principal da aplicação.
│ ├── app.config.ts # Arquivo de configuração da aplicação.
│ ├── app.resolvers.ts # Arquivo de resolvers para carregamento de dados antes da navegação.
│ └── app.routes.ts # Arquivo de configuração das rotas da aplicação.
├── assets # Diretório que contém arquivos estáticos, como imagens, fontes, etc.
├── environments # Diretório que contém arquivos de configuração de ambiente (ex: desenvolvimento, produção).
├── styles # Diretório que contém arquivos de estilos globais da aplicação.
├── index.html # Arquivo HTML principal que serve como entrada para a aplicação.
├── main.ts # Arquivo TypeScript principal que inicializa a aplicação.
├── tools # Diretório que contém scripts e ferramentas auxiliares para o desenvolvimento e build.
├── .dockerignore # Arquivo que especifica quais arquivos e diretórios devem ser ignorados pelo Docker.
├── .editorconfig # Arquivo de configuração para editores de código, garantindo consistência de formatação.
├── .eslintignore # Arquivo que especifica quais arquivos e diretórios devem ser ignorados pelo ESLint.
├── .eslintrc.json # Arquivo de configuração do ESLint, uma ferramenta de análise estática de código.
├── .gitignore # Arquivo que especifica quais arquivos e diretórios devem ser ignorados pelo Git.
├── .gitlab-ci.yml # Arquivo de configuração do GitLab CI/CD para automação de processos de build e deploy.
├── .prettierignore # Arquivo que especifica quais arquivos e diretórios devem ser ignorados pelo Prettier.
├── .prettierrc.json # Arquivo de configuração do Prettier, uma ferramenta de formatação de código.
├── angular.json # Arquivo de configuração principal do Angular CLI.
└── commitlint.config.js # Arquivo de configuração do Commitlint, uma ferramenta para garantir a conformidade das mensagens de commit.
Componentes¶
Os componentes são a base de uma aplicação Angular. Eles encapsulam a lógica e a interface do usuário, promovendo a modularidade e a reutilização. Cada componente é composto por:
- Template: Define a interface do usuário usando HTML.
- Classe: Contém a lógica e os dados do componente, escrita em TypeScript.
- Estilos: Define a aparência do componente usando CSS ou SCSS.
Cada componente possue 4 arquivos:
nome-do-componente.component.html
: O template do componente.nome-do-componente.component.css
(ou.scss
): Os estilos do componente.nome-do-componente.component.ts
: A classe do componente.nome-do-componente.component.spec.ts
: Testes unitários para o componente.
Estrutura dos arquivos¶
- HTML (.component.html)
- CSS (.component.css)
- TypeScript (.component.ts)
import { Component } from "@angular/core";
@Component({
selector: "app-nome-do-componente",
templateUrl: "./nome-do-componente.component.html",
styleUrls: ["./nome-do-componente.component.css"],
})
export class NomeDoComponente {
titulo = "Olá, Angular!";
}
Rotas¶
As rotas no Angular são uma forma de navegar entre diferentes partes de uma aplicação sem recarregar a página. Elas permitem que você crie uma SPA (Single Page Application) com uma navegação fluida e rápida. As rotas são definidas usando a biblioteca Angular Router, que permite mapear URLs para componentes específicos.
Conceitos Principais¶
- RouterModule: Um módulo que fornece a funcionalidade de roteamento e diretivas para navegação.
- Routes: Um array utilizado na configuração das rotas da aplicação.
- RouterOutlet: Uma diretiva usada para definir onde o conteúdo correspondente à rota deve ser exibido no arquivo HTML.
- RouterLink: Uma diretiva usada para vincular elementos HTML a uma rota específica.
Implementação¶
Para implementar as rotas na aplicação, é necessário importar e configurar o RouterModule
no módulo principal da aplicação.
import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";
import { HomeComponent } from "./home/home.component";
import { AboutComponent } from "./about/about.component";
const routes: Routes = [
{ path: "", pathMatch: "full", redirectTo: "inicio" }, // Define uma rota que redireciona da raiz para "/inicio"
{
path: "",
canActivate: [AuthGuard], // Especifica que a rota requer que o guard "AuthGuard" seja ativado
canActivateChild: [AuthGuard], // Especifica que os filhos da rota também requerem o guard "AuthGuard"
component: LayoutComponent, // Define o componente que será usado ao carregar essa rota
resolve: {
// Busca os dados iniciais (ex.: domínio - opcional) antes de carregar o componente
initialData: initialDataResolver,
},
children: [
{
path: "inicio", // Define uma rota filha para "inicio"
loadChildren: () =>
import("app/modules/admin/inicio/inicio.routes"), // Carrega o módulo de rotas para "inicio" dinamicamente
},
{
path: "dashboard", // Define uma rota filha para "dashboard"
loadChildren: () =>
import("app/modules/admin/dashboard/dashboard.routes"), // Carrega o módulo de rotas para "dashboard" dinamicamente
},
{
path: "users/:id", // Define uma rota filha para "users" com um parâmetro ID
loadChildren: () =>
import("app/modules/admin/users/users.routes"), // Carrega o módulo de rotas para "users" dinamicamente
},
],
},
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
export class AppRoutingModule {}
Para que o conteúdo das rotas seja exibido, você precisa adicionar a diretiva RouterOutlet no template principal da sua aplicação.
Em seguida, basta criar links de navegação, é ncessário utilizar a diretiva RouterLink
.
Para rotas com parâmetros, é possível obter o valor utilizando a classe ActivatedRoute
no arquivo Typescript do componente.
import { ActivatedRoute } from "@angular/router";
@Component({
selector: "app-user",
templateUrl: "./user.component.html",
})
export class UserComponent implements OnInit {
userId: string;
constructor(private _route: ActivatedRoute) {}
ngOnInit(): void {
this.userId = this._route.snapshot.paramMap.get("id");
}
}
Rotas de Guarda (Guards)¶
Os guards são usados para proteger rotas, controlando o acesso com base em condições específicas.
import { Injectable } from "@angular/core";
import {
CanActivate,
ActivatedRouteSnapshot,
RouterStateSnapshot,
UrlTree,
} from "@angular/router";
import { Observable } from "rxjs";
import { AuthService } from "./auth.service";
@Injectable({
providedIn: "root",
})
export class AuthGuard implements CanActivate {
constructor(private _authService: AuthService) {}
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot
):
| Observable<boolean | UrlTree>
| Promise<boolean | UrlTree>
| boolean
| UrlTree {
// Retorna true ou false, a depender da lógica implementada para a proteção da rota.
return this._authService.isLoggedIn();
}
}
Formulários¶
Os formulários reativos (Reactive Form) no Angular oferecem uma abordagem baseada no modelo para gerenciar o estado dos campos de formulários cujos valores mudam ao longo do tempo. Diferente dos Template-driven Forms, que são baseados em templates, os Reactive Forms são baseados em código e fornecem mais controle e previsibilidade.
Conceitos Principais¶
- FormControl: Representa um único campo de entrada de dado.
- FormGroup: Agrupa vários controles de formulário em uma estrutura unificada.
- FormArray: Gerencia um array de instâncias de FormControl ou FormGroup.
Implementação¶
Importando o módulo ReactiveFormsModule
¶
Para usar os Reactive Forms, é necessário importar o módulo ReactiveFormsModule
no módulo principal da aplicação.
import { ReactiveFormsModule } from "@angular/forms";
@NgModule({
imports: [ReactiveFormsModule],
})
export class AppModule {}
Criando FormControls
¶
Um FormControl
pode ser criado e associado a um campo de entrada no componente.
import { Component } from "@angular/core";
import { FormControl } from "@angular/forms";
@Component({
selector: "app-name-editor",
template: `
<label for="name">Name: </label>
<input id="name" [formControl]="name" />
<p>Value: {{ name.value }}</p>
<button (click)="updateName()">Update Name</button>
`,
})
export class NameEditorComponent {
name = new FormControl("");
updateName() {
this.name.setValue("Nancy");
}
}
Criando FormGroups
¶
Um FormGroup
agrupa múltiplos FormControl
em uma estrutura de formulário.
import { Component } from "@angular/core";
import { FormGroup, FormControl } from "@angular/forms";
@Component({
selector: "app-profile-editor",
template: `
<form [formGroup]="profileForm">
<label for="first-name">First Name: </label>
<input id="first-name" formControlName="firstName" />
<label for="last-name">Last Name: </label>
<input id="last-name" formControlName="lastName" />
</form>
`,
})
export class ProfileEditorComponent {
profileForm = new FormGroup({
firstName: new FormControl(""),
lastName: new FormControl(""),
});
}
Validando Formulários¶
As validações podem ser adicionadas aos controles para garantir a integridade dos dados.
import { Validators } from "@angular/forms";
profileForm = new FormGroup({
firstName: new FormControl("", Validators.required),
lastName: new FormControl("", Validators.maxLength(10)),
});
Exemplo Prático: Formulário de Edição de Perfil¶
import { Component } from "@angular/core";
import { FormBuilder, FormGroup } from "@angular/forms";
@Component({
selector: "app-profile-editor",
template: `
<form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
<label for="first-name">First Name: </label>
<input id="first-name" formControlName="firstName" />
<label for="last-name">Last Name: </label>
<input id="last-name" formControlName="lastName" />
<button type="submit">Submit</button>
</form>
`,
})
export class ProfileEditorComponent {
profileForm: FormGroup;
constructor(private fb: FormBuilder) {
this.profileForm = this.fb.group({
firstName: [""],
lastName: [""],
});
}
onSubmit() {
console.warn(this.profileForm.value);
// O resultado será um objeto com os valores informados nos inputs. Ex.:
// {
// firstName: "João",
// lastName: "Pedro"
// }
}
}
Angular HTTP Client¶
A interface HttpClient
do Angular é um serviço que facilita a comunicação com servidores HTTP, tornando a tarefa de fazer requisições HTTP mais simples e eficiente. Ele suporta métodos de requisição como GET
, POST
, PUT
, DELETE
, entre outros, e é baseado em Observables, permitindo o uso de operadores do RxJS para manipulação de dados e tratamento de erros.
Implementação¶
Importando o módulo HttpClientModule
¶
Para utilizar o HttpClient
, você precisa importá-lo no módulo principal da aplicação.
import { HttpClientModule } from "@angular/common/http";
@NgModule({
imports: [HttpClientModule],
})
export class AppModule {}
Realizando Requisições HTTP¶
Requisição GET¶
Para realizar uma requisição GET, use o método HttpClient.get()
. Este método retorna um Observable que emite os dados da resposta.
import { HttpClient } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { Observable } from "rxjs";
@Injectable({
providedIn: "root",
})
export class DataService {
constructor(private http: HttpClient) {}
getData(): Observable<MyDataType> {
return this.http.get<MyDataType>("https://api.example.com/data");
}
}
Requisição POST¶
Para enviar dados ao servidor, utilize o método HttpClient.post()
. Este método aceita um objeto no corpo da requisição (payload) que será enviado ao servidor.
import { HttpClient } from "@angular/common/http";
import { Injectable } from "@angular/core";
@Injectable({
providedIn: "root",
})
export class DataService {
constructor(private http: HttpClient) {}
postData(data: MyDataType): Observable<MyDataType> {
return this.http.post<MyDataType>("https://api.example.com/data", data);
}
}
Configurando Cabeçalhos e Parâmetros¶
Você pode adicionar headers e parâmetros às suas requisições utilizando objetos de configuração.
Headers¶
import { HttpHeaders } from "@angular/common/http";
const headers = new HttpHeaders({
"Content-Type": "application/json",
Authorization: "Bearer my-token",
});
this.http.get<MyDataType>("https://api.example.com/data", { headers });
Parâmetros¶
import { HttpParams } from "@angular/common/http";
const params = new HttpParams().set("page", "1").set("pageSize", "10");
this.http.get<MyDataType>("https://api.example.com/data", { params });
Manipulação de Erros¶
Utilize operadores do RxJS para capturar e tratar erros em suas requisições.
import { catchError } from "rxjs/operators";
import { throwError } from "rxjs";
this.http
.get<MyDataType>("https://api.example.com/data")
.pipe(
catchError((error) => {
console.error("Erro na requisição", error);
return throwError(error);
})
)
.subscribe((data) => {
// Processar os dados
});
Manipulação de Eventos de Progresso¶
Você pode monitorar o progresso de uploads e downloads configurando a opção reportProgress
.
this.http
.post("https://api.example.com/upload", formData, {
reportProgress: true,
observe: "events",
})
.subscribe((event) => {
if (event.type === HttpEventType.UploadProgress) {
console.log(`Progresso: ${event.loaded} de ${event.total}`);
} else if (event.type === HttpEventType.Response) {
console.log("Upload completo!");
}
});
Exemplo Prático: Implementação de um serviço de usuários¶
import { HttpClient } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { Observable } from "rxjs";
export interface User {
id: number;
name: string;
email: string;
}
@Injectable({
providedIn: "root",
})
export class UserService {
private apiUrl = "https://api.example.com/users";
constructor(private http: HttpClient) {}
getUsers(): Observable<User[]> {
return this.http.get<User[]>(this.apiUrl);
}
getUser(id: number): Observable<User> {
return this.http.get<User>(`${this.apiUrl}/${id}`);
}
createUser(user: User): Observable<User> {
return this.http.post<User>(this.apiUrl, user);
}
updateUser(id: number, user: User): Observable<User> {
return this.http.put<User>(`${this.apiUrl}/${id}`, user);
}
deleteUser(id: number): Observable<void> {
return this.http.delete<void>(`${this.apiUrl}/${id}`);
}
}