Angular¶
Angular é um framework do Google para construir aplicações web de página única (SPAs) — e, com ferramentas ligadas a ele, aplicativos móveis e desktop — usando HTML, CSS e TypeScript. Compete com React e Vue em vagas de front-end.
Sobre as versões
As fontes cobrem o Angular 2/4 (2016–2017) e o Angular 11 (2021). Os conceitos centrais (componentes, templates, data binding, injeção de dependência, módulos, rotas, formulários, serviços e RxJS) continuam válidos; o que mudou está em O que mudou nas versões recentes. Os trechos marcados como complemento não estão nos livros.
O que é e por que SPA¶
Definição: SPA (Single Page Application)
Aplicação que carrega uma única página e, a partir daí, troca partes do HTML (templates) no próprio navegador. O servidor só devolve dados brutos (JSON); não há recarregamento da página inteira.
| Vantagem de uma SPA | Por quê |
|---|---|
| Experiência | Parece uma aplicação desktop: só trechos da tela mudam |
| Desempenho | Transições entre telas não precisam ser montadas e enviadas pelo servidor; tráfego menor |
| Carga no servidor | Ele só recebe a requisição, processa e devolve JSON |
Complemento — contrapartida: SEO e primeiro carregamento exigem cuidado (renderização no servidor/SSR, pré-renderização).
Angular x AngularJS: o Angular 2+ não é continuação do AngularJS (1.x): foi reescrito do zero,
mais rápido (menos interações com o DOM), baseado em componentes e TypeScript. Desde o Angular 2
há um ciclo de lançamentos a cada ~6 meses com versionamento semântico; a equipe pede que se diga
apenas "Angular" (e não "Angular 2/3/4…"), para evitar a impressão de que cada versão é um
framework novo. Atualizar entre versões costuma ser só trocar os pacotes (ng update hoje).
Pré-requisitos: ES6 e TypeScript¶
ECMAScript (JavaScript moderno)¶
ECMAScript (ES) é a especificação do JavaScript; desde 2015 (ES6/ES2015) há uma edição por ano. Recursos que aparecem o tempo todo no Angular:
let nome = 'Angular'; // let: escopo de BLOCO (var tem escopo de função/global)
const PI = 3.14; // const: não pode ser reatribuída
function somar(x: number, y = 1) { return x + y; } // parâmetro padrão (default parameter)
const somar2 = (x: number, y = 1) => x + y; // arrow function
const [a, b] = [1, 2]; // destructuring de array
const { livro, autor } = { livro: 'Angular', autor: 'X' }; // destructuring de objeto
[2, 3, 4].map(n => n * 2); // [4, 6, 8] transforma cada elemento
['jorge', 'carlos'].filter(n => n.includes('a')); // ['carlos'] mantém os que passam no teste
[1, 2, 3].reduce((acc, n) => acc + n, 0); // 6 reduz a um único valor
TypeScript¶
Definição: TypeScript
Superset de JavaScript da Microsoft com tipagem estática e sintaxe de classes parecida com
Java/C#. É compilado (transpilado) para JavaScript, porque os navegadores não o executam;
o tsconfig.json define o alvo de compilação. Os polyfills garantem recursos modernos em
navegadores antigos.
class Pessoa {
private nome: string; // visibilidade: public (padrão), private, protected
constructor(nome: string, public idade?: number) { this.nome = nome; } // ? = opcional
saudar(): string { return `Olá, ${this.nome}`; }
logar(msg: string | number): void { console.log(msg); } // união de tipos; void = sem retorno
}
function qualquer(x: any) { } // any desliga a checagem de tipos: evite
interface ICrud<T> { get(id: string): Observable<T>; } // interfaces e genéricos
Ambiente e Angular CLI¶
O ambiente usa Node.js (executa JavaScript fora do navegador) e o npm (gerenciador de pacotes,
package.json), e o Angular CLI (ng) para criar, gerar artefatos, testar e construir.
npm install -g @angular/cli
ng new minha-app # cria o projeto
ng serve -o # servidor de desenvolvimento em localhost:4200 (recarrega ao salvar)
ng generate component lista-pessoa # ng g c — cria .ts, .html, .css e .spec.ts
ng g service alerta # ng g s
ng g module admin --routing # ng g m
ng test # testes unitários (Karma + Jasmine)
ng lint # boas práticas do guia de estilo
ng build # gera a pasta dist/ para produção (no passado: ng build --prod)
Estrutura do projeto: src/app (todo o código da aplicação), app.module.ts (módulo raiz),
main.ts (bootstrap), index.html (a única página), environments/ (configurações por ambiente:
environment.ts e environment.prod.ts), angular.json (configuração do projeto), package.json
(dependencies para produção e devDependencies só para desenvolvimento), node_modules.
Como a aplicação inicia: index.html carrega → main.ts chama
platformBrowserDynamic().bootstrapModule(AppModule) → o AppModule declara os objetos e indica, em
bootstrap, o componente raiz (AppComponent) → o Angular lê o @Component, renderiza o
template e mostra a aplicação. (O bootstrap do Angular não tem relação com o framework CSS
Bootstrap.)
Arquitetura: as peças de uma aplicação¶
flowchart LR
M["NgModule<br/>(declarations, imports, providers, bootstrap)"] --> C["Componente<br/>(classe + template + metadata)"]
C <-->|"data binding"| T["Template (HTML)"]
C -->|"injeção de dependência"| S["Serviços (@Injectable)"]
D["Diretivas e pipes"] --> T
S --> API[("API / Firebase")]
R["Roteador"] --> C
Componente, template e metadata¶
Definição: Componente
A unidade central do Angular: uma classe TypeScript que controla uma view + um template
HTML + metadados do decorador @Component. Em Angular "tudo é componente"; uma página é a
composição de componentes pequenos, cada um com uma responsabilidade (modularização: mais fácil de
construir, testar e reutilizar).
@Component({
selector: 'app-lista-pessoa', // como a tag aparece em outro template
templateUrl: './lista-pessoa.component.html', // (ou template: inline)
styleUrls: ['./lista-pessoa.component.css'], // estilos do componente
providers: [PessoaService] // serviços visíveis só aqui (opcional)
})
export class ListaPessoaComponent implements OnInit {
pessoas: string[] = [];
constructor(private service: PessoaService) { } // injeção de dependência
ngOnInit() { this.pessoas = this.service.getPessoas(); } // gancho de ciclo de vida
}
- A classe contém só a lógica de controle da view: regras de negócio, validações e acesso a dados vão para serviços.
- Um decorador (
@Component,@NgModule,@Injectable,@Input...) anexa metadados à classe, ao método ou à propriedade. - Ciclo de vida:
ngOnInit()(depois de definir as propriedades de entrada — o lugar de inicializar e chamar serviços),ngOnChanges,ngOnDestroy(limpeza, cancelar subscriptions). - O construtor é para declarar dependências e inicializações simples.
Data binding: quatro formas de ligar classe e template¶
| Forma | Sintaxe | Direção | Exemplo |
|---|---|---|---|
| Interpolação | {{ valor }} |
classe → template | <h1>{{ titulo }}</h1> |
| Property binding | [propriedade]="expr" |
classe → propriedade da tag | <img [src]="foto"> |
| Event binding | (evento)="acao()" |
template → classe | <button (click)="salvar()"> |
| Two-way binding | [(ngModel)]="variavel" |
ambas (combina as duas anteriores, "banana na caixa") | <input [(ngModel)]="nome"> |
Eventos úteis: (click), (keyup), (keyup.enter), (blur), (ngSubmit). Variável de referência do
template (#campo) dá acesso a um elemento ou ao ngModel dentro do próprio template.
Diretivas¶
Diretivas modificam o DOM. Os próprios componentes são um tipo de diretiva.
| Tipo | O que faz | Exemplos |
|---|---|---|
Estruturais (prefixo *) |
Adicionam/removem elementos do DOM | *ngIf, *ngFor, ngSwitch |
| De atributo | Mudam aparência/comportamento sem alterar a estrutura | [ngClass], [ngStyle], [(ngModel)] |
<li *ngFor="let pessoa of pessoas; let i = index">{{ i + 1 }} - {{ pessoa }}</li>
<div *ngIf="logado; else visitante">Bem-vindo!</div> <!-- else existe desde o Angular 4 -->
<ng-template #visitante><p>Faça login</p></ng-template>
<span [ngClass]="{ ativo: ok, erro: !ok }" [ngStyle]="{ 'font-size.px': tamanho }">...</span>
<ng-content></ng-content> <!-- "projeção" de conteúdo: o que o pai coloca entre as tags do componente -->
- No
ngFor,index as iecount as totalexpõem posição e quantidade;trackBy(complemento) evita recriar todos os elementos ao mudar a lista. - Variáveis de template com
async(dados$ | async) assinam um Observable sem código manual.
Serviços e injeção de dependência¶
Definição: Serviço e injeção de dependência (DI)
Serviço é uma classe @Injectable() com lógica que não pertence a um componente:
regras de negócio, validação, log, tratamento de erros, acesso a servidor/banco — o que também
permite reaproveitar e testar. Injeção de dependência: o componente declara no construtor
o que precisa e o Angular fornece a instância, gerenciada por um contêiner (reutilizando a que
já existe), em vez de usar new.
@Injectable({ providedIn: 'root' }) // instância única na aplicação (Angular 6+)
export class AlertaService {
msgAlerta(): void { alert('Olá'); }
}
constructor(private alerta: AlertaService) { } // o Angular injeta
- Sem provider registrado:
No provider for AlertaService!— o serviço precisa ser fornecido (providedIn: 'root',providersdo módulo ou do componente). - Regra de escopo: declarado em
providersdo componente → instância própria, só dele; declarado no módulo/raiz → instância compartilhada por todos. Serviço usado por mais de um componente deve ser global. - Instanciar manualmente (
new Servico()) é má prática: perde-se o gerenciamento e podem surgir várias instâncias. - O guia de estilo recomenda classes de até ~400 linhas e métodos de até ~75.
- Dependências podem ser opcionais (
@Optional()), e serviços podem injetar outros serviços. - Relação com o padrão em Dependency Injection e com o Spring.
NgModule¶
Módulos reúnem componentes, diretivas, pipes e serviços de mesma finalidade; toda aplicação tem ao
menos o AppModule. Campos do @NgModule:
| Campo | Para quê |
|---|---|
declarations |
Componentes, diretivas e pipes que pertencem a este módulo (se não for declarado, o Angular não o reconhece) |
imports |
Outros módulos usados (BrowserModule, FormsModule, HttpClientModule, módulos de bibliotecas) |
providers |
Serviços disponíveis para a injeção |
exports |
O que o módulo disponibiliza a quem o importar (módulos compartilhados) |
bootstrap |
Componente raiz (só no módulo raiz) |
Convenção de organização dos imports no arquivo: primeiro os do Angular, depois os de terceiros e por
último os do próprio projeto, separados por linha em branco. Sempre dois passos: importar o símbolo
e declará-lo no @NgModule apropriado.
Comunicação entre componentes¶
@Input(): o pai passa dados ao filho —@Input() menu: string;no filho e<app-filho [menu]="lista"></app-filho>no pai.@Output()+EventEmitter: o filho avisa o pai — o filho emite o evento e o pai o trata.- Outras formas: serviços compartilhados (com Observables), roteador, projeção (
ng-content).
// filho
@Input() menu!: string[];
@Output() nomeClicado = new EventEmitter<string>();
enviar(item: string) { this.nomeClicado.emit(item); }
Formulários¶
O Angular tem duas abordagens:
| Template-driven (orientado a template) | Reativos (reactive forms) | |
|---|---|---|
| Quando | Formulário simples (ex.: login) | Formulários complexos, reutilizáveis e escaláveis |
| Módulo | FormsModule |
ReactiveFormsModule |
| Como | ngModel, validações por atributos HTML |
FormGroup/FormControl criados na classe, [formGroup] e formControlName no template |
| Validação | required, minlength, maxlength, email; #campo="ngModel" expõe valid, errors, pristine, touched |
Validators.required, Validators.email, vários em lista; validadores próprios |
<!-- template-driven -->
<form #cadastro="ngForm" (ngSubmit)="enviar()">
<input name="email" [(ngModel)]="email" #emailCtl="ngModel" required email>
<div *ngIf="emailCtl.invalid && emailCtl.touched">
<small *ngIf="emailCtl.errors?.['required']">Email obrigatório</small>
<small *ngIf="emailCtl.errors?.['email']">Email inválido</small>
</div>
<button type="submit" [disabled]="cadastro.form.invalid">Enviar</button>
</form>
// reativo
this.form = this.fb.group({
nome: new FormControl('', Validators.required),
email: new FormControl('', [Validators.required, Validators.email]),
});
ngModelGroup agrupa campos. Prefira o reativo quando houver regras, campos dinâmicos ou testes.
Rotas, guardas e lazy loading¶
O roteador associa URLs a componentes; o componente do <router-outlet> marca onde a tela
roteada aparece; routerLink cria links e routerLinkActive marca o ativo; Router.navigate([...])
navega por código.
const routes: Routes = [
{ path: '', redirectTo: 'login', pathMatch: 'full' },
{ path: 'login', component: LoginComponent },
{ path: 'admin/painel',
loadChildren: () => import('./painel/painel.module').then(m => m.PainelModule), // lazy loading
canActivate: [AuthGuard] }, // guarda de rota
];
- Lazy loading: dividir a aplicação em módulos carregados só quando o usuário navega para a
rota, reduzindo o tempo de carga inicial (usa a importação dinâmica
import()). - Guardas (
CanActivatee similares) decidem se uma rota pode ser ativada; por exemplo, redirecionar para o login se não houver usuário autenticado:
canActivate(): Observable<boolean> {
return this.afAuth.authState.pipe(
take(1), map(user => !!user),
tap(logado => { if (!logado) this.router.navigate(['/login']); }));
}
CommonModule, FormsModule, módulos de biblioteca de componentes
exportados em um único módulo) evitam repetir importações. Guardas protegem a navegação, mas a
segurança real está no servidor (regras do banco, autorização na API).
Pipes e RxJS¶
- Pipe transforma um valor para exibição:
{{ valor | date }},uppercase,currency,async. Pode-se criar um próprio com@Pipe({ name: 'filtro' })implementandoPipeTransform.transform()(ex.: filtrar uma lista por departamento). Observable(RxJS): fluxo de dados assíncronos que pode emitir vários valores no tempo; é a base deHttpClient, do roteador e dos formulários.Promiserepresenta um resultado futuro.subscribe()(ou o pipeasync) assina o fluxo; operadores comomap,take,tapefilterse combinam em.pipe(...). Cancele as assinaturas manuais emngOnDestroy.
Firebase: back-end como serviço¶
Firebase é a plataforma de serviços do Google para aplicações: o Angular cuida da interface e o Firebase da infraestrutura (escalável e com plano gratuito). Biblioteca oficial: AngularFire.
| Serviço | Para quê |
|---|---|
| Authentication | Login pronto (e-mail/senha, Google, Facebook...): signInWithEmailAndPassword, signOut, sendPasswordResetEmail; authState é um Observable do usuário |
| Cloud Firestore | Banco NoSQL de documentos (coleções → documentos), com sincronização e consultas em escala (NoSQL) |
| Cloud Storage | Armazenamento de arquivos (fotos, anexos); upload devolve o progresso como Observable e a URL de download |
| Cloud Functions | Funções no servidor disparadas por eventos (ex.: criar o usuário de autenticação quando um documento é criado; enviar e-mail quando uma requisição é atualizada); implantadas com a firebase-tools (firebase deploy) |
| Hosting | Hospedagem do SPA com HTTPS, histórico de versões e rollback (firebase init hosting, firebase deploy --only hosting) |
- Regras de segurança (Security Rules) controlam quem lê e grava: modo bloqueado (nega tudo) ou
teste (libera tudo — nunca em produção). Exemplo: permitir só usuários autenticados
(
allow read, write: if request.auth != null;), com regras por coleção/operação. - A configuração do Firebase para a web (chaves no
environment.ts) identifica o projeto, mas não é segredo de acesso: quem protege os dados são as regras de segurança. Já segredos de servidor (chaves de contas de serviço,.envcom senhas) jamais vão ao repositório. - O Firebase só aceita objetos literais (JSON simples): modelos TypeScript com métodos precisam ser
convertidos (a fonte usa a biblioteca
class-transformer,classToPlain/plainToClass). - Lock-in: o Firestore e as functions prendem a aplicação ao Google (Nuvem: lock-in).
Padrão: serviço genérico de CRUD¶
Para não repetir código nem misturar acesso a dados nos componentes (o que o guia de estilo desaconselha), define-se uma interface genérica e uma classe base abstrata que as entidades herdam:
export interface ICrud<T> {
get(id: string): Observable<T>;
list(): Observable<T[]>;
createOrUpdate(item: T): Promise<T>;
delete(id: string): Promise<void>;
}
export abstract class ServiceFirebase<T extends Model> implements ICrud<T> {
protected ref: AngularFirestoreCollection<T>;
constructor(protected type: { new(): T }, protected firestore: AngularFirestore, public path: string) {
this.ref = this.firestore.collection<T>(this.path);
}
// get / list / createOrUpdate / delete implementados uma única vez (valueChanges() devolve um Observable)
}
@Injectable({ providedIn: 'root' })
export class DepartamentoService extends ServiceFirebase<Departamento> {
constructor(firestore: AngularFirestore) { super(Departamento, firestore, 'departamentos'); }
}
Mesmo princípio dos padrões Repository/DAO (Acesso a dados) e das classes abstratas/genéricos de OO: o que varia (entidade e coleção) vai no construtor; o comportamento comum fica na base. Convenção: coleção com o nome da entidade no plural.
Testes, build e deploy¶
- Unitários: Karma + Jasmine (arquivos
.spec.ts, um por componente/serviço). Integração/e2e: Protractor na época (hoje descontinuado: Cypress, Playwright). Pirâmide em Qualidade. - Build:
ng buildgera a pastadist/otimizada (minificação e tree shaking) e AOT (Ahead of Time: converte HTML e TypeScript em JavaScript eficiente antes do navegador baixá-lo, com renderização mais rápida). Na versão 4 o código gerado diminuiu até 60%. - Ivy (padrão desde o Angular 9): reescrita do compilador e do runtime — compilação incremental, bundles menores, carregamento preguiçoso de componentes. Não muda como se escreve o código.
- Variáveis por ambiente em
environments/; esteira de CI/CD em CI/CD.
O que mudou nas versões recentes¶
Complemento (o que o código dos livros faria diferente hoje):
| Livro (Angular 2–11) | Angular atual (17+) |
|---|---|
NgModule obrigatório |
Componentes standalone (standalone: true, imports: [...] no próprio componente) |
*ngIf, *ngFor, *ngSwitch |
Controle de fluxo nativo: @if (...) {...} @else {...}, @for (item of lista; track item.id), @switch |
| Injeção só por construtor | Função inject() também (private http = inject(HttpClient)) |
HttpModule / Http (Angular 2) |
HttpClient (provideHttpClient()), respostas tipadas e interceptors |
Detecção de mudanças com zone.js |
Signals (signal(), computed(), effect()) para estado reativo com detecção mais fina |
| TSLint, Protractor, Webpack | ESLint, Cypress/Playwright, builder baseado em esbuild/Vite |
ng build --prod |
ng build já é de produção por padrão |
| AngularFire 6 (API namespaced) | AngularFire modular (7+), com funções em vez de classes |
AngularJS (1.x): o legado¶
O AngularJS (2010–2021, fim do suporte) foi o framework MVC do Google que popularizou as SPAs e o data binding. Muitos sistemas ainda o usam, e em entrevistas ele aparece como termo de comparação. Dá para entender o Angular moderno como a resposta aos seus problemas de desempenho e escala.
Definição: AngularJS
Framework JavaScript que estende o HTML com diretivas e expressões: o desenvolvedor escreve o template HTML e o AngularJS mantém a página
sincronizada com o modelo ($scope) por data binding bidirecional, sem manipular o DOM manualmente.
| Conceito (AngularJS 1.x) | O que faz | Equivalente no Angular moderno |
|---|---|---|
Módulo (angular.module) e ng-app |
Agrupa e inicializa a aplicação | NgModule / standalone components |
Controller + $scope |
Expõe dados e ações para a view | Componente (classe) |
Expressão {{ nome }} |
Interpola dados no HTML | Interpolação {{ }} |
Diretivas ng-repeat, ng-model, ng-click, ng-if, ng-class |
Estendem o HTML | *ngFor/@for, [(ngModel)], (click), *ngIf/@if, [ngClass] |
| Data binding bidirecional | Alterou no campo, muda o modelo e vice-versa (via digest cycle, custoso em listas grandes) | Binding unidirecional por padrão, com detecção de mudanças por componente (e signals) |
Serviços/factories ($http, $resource) |
Lógica reutilizável e acesso a APIs, com injeção de dependência | Serviços @Injectable + HttpClient |
Rotas ngRoute ($routeProvider, $routeParams) |
Navegação da SPA | @angular/router |
Filtros (| currency) |
Formatam valores no template | Pipes |
| Diretivas próprias | Componentes de UI reutilizáveis | Componentes e diretivas |
Promises ($q) |
Resultado assíncrono | Observable (RxJS) e async/await |
Pontos que costumam ser perguntados:
- Injeção de dependência por nome: o AngularJS descobre as dependências pelo nome dos parâmetros da função, o que quebra na minificação
(os nomes são encurtados). A solução é a anotação em array (
['$scope', '$http', function($scope, $http){...}]) oung-annotate. O Angular moderno usa types e o compilador. - Digest cycle: a cada evento o AngularJS percorre todas as watches até o modelo estabilizar — por isso muitas ligações deixam a página lenta.
- Por que migrar: fim do suporte, desempenho, TypeScript, componentes e ferramentas modernas (CLI, AOT). A migração costuma ser incremental (ngUpgrade) ou por reescrita.
- Testes: Karma + Jasmine, com
angular-mockse$httpBackendpara simular o back-end; testes de ponta a ponta com Protractor (hoje descontinuado, substituído por Playwright/Cypress).
Em conjunto com Node, Express e MongoDB, formou a MEAN Stack (Node.js e Express).
Perguntas comuns de entrevista (resumo)¶
| Pergunta | Resposta curta |
|---|---|
| O que é uma SPA? | Aplicação que carrega uma página e troca templates no navegador, buscando só dados (JSON) no servidor |
| Angular x AngularJS? | O Angular 2+ foi reescrito do zero, com componentes, TypeScript e melhor desempenho; não é continuação do AngularJS |
| O que é um componente? | Classe decorada com @Component + template + estilos; unidade de UI reutilizável |
| Quais os tipos de data binding? | Interpolação, property, event e two-way ([(ngModel)]) |
| Diretiva estrutural x de atributo? | Estrutural muda a estrutura do DOM (*ngIf, *ngFor); de atributo muda aparência/comportamento (ngClass, ngStyle) |
| O que é injeção de dependência no Angular? | O componente declara no construtor o que precisa e o Angular fornece instâncias gerenciadas dos serviços |
| Onde declarar um serviço? | providedIn: 'root'/módulo para compartilhar; providers do componente para instância própria |
@Input x @Output? |
@Input: pai → filho; @Output + EventEmitter: filho → pai |
| Template-driven x reactive forms? | Template-driven é simples, baseado em ngModel; reativos criam o modelo na classe, são mais testáveis e escaláveis |
| O que é lazy loading? | Carregar um módulo só quando a rota for acessada, reduzindo o carregamento inicial |
Observable x Promise? |
O Observable pode emitir vários valores e ser cancelado; a Promise resolve uma única vez |
| O que é AOT? | Compilação do Angular antes de o navegador receber o código, com renderização mais rápida |