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: 'ops@example.com',
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.
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.
Artigos relacionados
Workflow Obsidian para CLAUDE.md com Claude Code
Transforme notas de trabalho do Obsidian em notas operacionais CLAUDE.md para preservar contexto.
Claude Code Revenue CTA Routing: artigos para PDF, Gumroad e consultoria
Um fluxo com Claude Code para levar leitores ao PDF grátis, Gumroad ou consultoria conforme intenção.
Regras de handoff para equipes com Claude Code: evidências, permissões, rollback e receita
Formato prático para entregar trabalho do Claude Code com prova, permissões, rollback, PDF grátis, Gumroad e consultoria.