Claude Code para Angular: CLI, standalone components, formulários, HTTP e testes
Workflow com Claude Code para Angular CLI, componentes standalone, Reactive Forms, HttpClient, testes, E2E e revisão.
Claude Code funciona melhor em Angular quando entende o projeto antes de editar. Em uma aplicação real, uma mudança passa por Angular CLI, standalone component, Reactive Forms, service tipado com HttpClient, testes unitários, E2E e uma revisão crítica do diff.
Um standalone component é um componente que declara as próprias dependências em imports, sem depender de NgModule. Reactive Forms é a abordagem em que valores e validações do formulário ficam explícitos no TypeScript. HttpClient é a API oficial do Angular para comunicação com backend. Esses termos precisam aparecer no prompt para evitar código antigo ou desalinhado com o repositório.
Use documentação oficial como base: Angular CLI, Reactive forms, HttpClient, Angular testing e Claude Code workflows. Para continuar, veja também dicas de TypeScript, estratégias de teste e boas práticas de CLAUDE.md.
Defina o limite de trabalho
Antes de pedir código, peça leitura do projeto. Claude Code precisa de um harness, ou seja, um quadro seguro de operação: arquivos permitidos, convenções, comandos de verificação e riscos a evitar.
Leia este projeto Angular antes de editar. Verifique package.json, angular.json e src/app.
Diga se o projeto usa standalone components, qual runner de testes está configurado,
onde HttpClient é fornecido e quais convenções de nome aparecem.
Ainda não edite arquivos.
| Área | Tarefa para Claude Code | Decisão humana |
|---|---|---|
| Angular CLI | comandos, caminhos, dependências | rotas e nomenclatura |
| Component | imports, template, signals, eventos | texto, acessibilidade, risco |
| Reactive Forms | FormGroup, validators, submit state | regras de negócio |
| Service / HTTP | tipos, métodos API, backend de teste | contrato, auth, erros |
| Testes | unit, E2E, regressão | cobertura e merge |
flowchart LR
P[Prompt] --> C[Angular CLI]
C --> A[Standalone component]
A --> F[Reactive Forms]
A --> S[Ticket service]
S --> H[HttpClient]
F --> U[Unit tests]
A --> E[E2E tests]
U --> R[Review]
E --> R
Crie uma base verificável com Angular CLI
Em um experimento novo, Angular CLI cria uma base limpa. Em um repositório existente, peça primeiro para Claude Code ler a configuração.
npm install -g @angular/cli
ng new support-desk-angular --standalone --routing --style css
cd support-desk-angular
ng generate component features/tickets/ticket-intake --standalone
ng generate service data/ticket
ng test
Rodar ng test antes da edição separa falhas antigas de regressões novas. Em trabalho paralelo, inclua no prompt que Claude Code deve tocar apenas o feature combinado e não reverter mudanças não commitadas de outras pessoas.
Comece pelo service tipado
Antes do formulário, defina o contrato de API. Assim o componente fica responsável por estado de UI e o service fica responsável por comunicação.
import { HttpClient } from '@angular/common/http';
import { inject, Injectable } from '@angular/core';
import { Observable } from 'rxjs';
export type TicketPriority = 'low' | 'medium' | 'high';
export interface TicketDraft {
title: string;
email: string;
priority: TicketPriority;
message: string;
}
export interface Ticket extends TicketDraft {
id: string;
createdAt: string;
}
@Injectable({ providedIn: 'root' })
export class TicketService {
private readonly http = inject(HttpClient);
private readonly baseUrl = '/api/tickets';
listTickets(): Observable<Ticket[]> {
return this.http.get<Ticket[]>(this.baseUrl);
}
createTicket(draft: TicketDraft): Observable<Ticket> {
return this.http.post<Ticket>(this.baseUrl, draft);
}
}
Em app standalone, registre HttpClient em app.config.ts.
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideHttpClient } from '@angular/common/http';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [provideRouter(routes), provideHttpClient()],
};
Um erro comum é misturar endpoint, texto de UI, retry e estado local no mesmo service. Mantenha o service simples. O componente decide como comunicar erro ao usuário.
Implemente o formulário standalone
O exemplo usa Reactive Forms e signal para o estado de salvamento. No prompt, deixe claro que ngModel não deve ser usado.
import { Component, computed, inject, signal } from '@angular/core';
import { ReactiveFormsModule, FormControl, FormGroup, Validators } from '@angular/forms';
import { finalize } from 'rxjs';
import { Ticket, TicketService, TicketPriority } from '../../../data/ticket.service';
@Component({
selector: 'app-ticket-intake',
standalone: true,
imports: [ReactiveFormsModule],
template: `
<form [formGroup]="form" (ngSubmit)="submit()" aria-label="Support ticket form">
<label>Title <input type="text" formControlName="title" /></label>
<label>Email <input type="email" formControlName="email" /></label>
<label>
Priority
<select formControlName="priority">
<option value="low">Low</option>
<option value="medium">Medium</option>
<option value="high">High</option>
</select>
</label>
<label>Message <textarea formControlName="message"></textarea></label>
@if (form.hasError('submit')) {
<p role="alert">Ticket could not be saved. Please try again.</p>
}
@if (savedTicket(); as ticket) {
<p role="status">Saved ticket {{ ticket.id }}</p>
}
<button type="submit" [disabled]="isSubmitDisabled()">
{{ saving() ? 'Saving...' : 'Create ticket' }}
</button>
</form>
`,
})
export class TicketIntakeComponent {
private readonly ticketService = inject(TicketService);
readonly saving = signal(false);
readonly savedTicket = signal<Ticket | null>(null);
readonly form = new FormGroup({
title: new FormControl('', { nonNullable: true, validators: [Validators.required, Validators.minLength(5)] }),
email: new FormControl('', { nonNullable: true, validators: [Validators.required, Validators.email] }),
priority: new FormControl<TicketPriority>('medium', { nonNullable: true }),
message: new FormControl('', { nonNullable: true, validators: [Validators.required, Validators.minLength(20)] }),
});
readonly isSubmitDisabled = computed(() => this.form.invalid || this.saving());
submit(): void {
this.form.markAllAsTouched();
this.form.setErrors(null);
if (this.form.invalid) return;
this.saving.set(true);
this.ticketService.createTicket(this.form.getRawValue()).pipe(
finalize(() => this.saving.set(false)),
).subscribe({
next: (ticket) => {
this.savedTicket.set(ticket);
this.form.reset({ title: '', email: '', priority: 'medium', message: '' });
},
error: () => this.form.setErrors({ submit: true }),
});
}
}
Os tropeços mais frequentes são misturar ngModel com formControlName, esquecer de bloquear duplo submit e enviar form.value com valores possivelmente nulos.
Casos de uso
Caso um: formulário de back office. O prompt deve listar campos, validações, estado de salvamento, sucesso e erro.
Caso dois: mover chamadas HTTP de um componente legado para um service. Peça tipos, separação de texto de UI e teste com HttpClient testing.
Caso três: corrigir bug com regressão. Se uma falha de API deixa o botão desabilitado, passe reprodução, expectativa e comando de teste.
Caso quatro: migração gradual para standalone. Limite a alteração a uma pasta de feature, preservando routing e providers.
Testes e revisão
Testes de HttpClient não devem acessar rede real.
import { TestBed } from '@angular/core/testing';
import { provideHttpClient } from '@angular/common/http';
import { provideHttpClientTesting, HttpTestingController } from '@angular/common/http/testing';
import { TicketService } from './ticket.service';
describe('TicketService', () => {
let service: TicketService;
let http: HttpTestingController;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [TicketService, provideHttpClient(), provideHttpClientTesting()],
});
service = TestBed.inject(TicketService);
http = TestBed.inject(HttpTestingController);
});
afterEach(() => http.verify());
it('creates a ticket through the API', () => {
const draft = {
title: 'Billing export is stuck',
email: '[email protected]',
priority: 'high' as const,
message: 'The monthly billing export has not finished for two hours.',
};
service.createTicket(draft).subscribe((ticket) => expect(ticket.id).toBe('T-100'));
const req = http.expectOne('/api/tickets');
expect(req.request.method).toBe('POST');
expect(req.request.body).toEqual(draft);
req.flush({ ...draft, id: 'T-100', createdAt: '2026-06-02T09:00:00.000Z' });
});
});
Para E2E, use ng e2e se o workspace tiver target configurado, ou Playwright se esse for o padrão do time. O mínimo é testar abrir a página, preencher campos, controlar a resposta da API e ver a mensagem de sucesso.
Revise criticamente este diff Angular.
Verifique imports/providers standalone, valores nullable em Reactive Forms,
duplo submit, separação service/UI, testes HttpClient,
cobertura unit/E2E, uso de any, subscriptions desnecessárias e acessibilidade.
Liste problemas com arquivo, linha e prioridade.
Resultado e CTA
Em um projeto Angular pequeno, um prompt vago gerou mistura de ngModel, texto de UI dentro do service e nenhum teste de falha. Dividir o trabalho em análise, service, formulário, teste HTTP, E2E e review deixou o diff muito mais claro. Para aplicar em equipe, coloque essas regras em CLAUDE.md e use treinamento e consultoria Claude Code para transformar o fluxo em prática repetível.
Artigos relacionados
Desenvolvimento Svelte e SvelteKit com Claude Code
Guia pratico para usar Claude Code com Svelte/SvelteKit: setup, runes, rotas, form actions, testes e mudancas seguras.
React com Claude Code em produção: componentes, Hooks, testes e revisão
Use Claude Code no React com componentes tipados, Hooks, testes, acessibilidade, performance e revisão.
Desenvolvimento com Storybook e Claude Code: UI, testes e CI
Configure Storybook com Claude Code: stories tipadas, interaction tests, CI e revisão visual com Chromatic.
PDF grátis: cheatsheet do Claude Code
Informe seu e-mail e baixe uma página com comandos, hábitos de revisão e workflows seguros.
Cuidamos dos seus dados e não enviamos spam.
Sobre o autor
Masa
Engenheiro focado em workflows práticos com Claude Code.