Skip to content
Back to skills

Angular Best Practices

ASecurity

Angular 21 development with modern best practices including signals, standalone components, reactive patterns, and accessibility. Use when creating Angular components, services, templates, or performing any Angular frontend development work. Covers TypeScript strict typing, signal-based state management, reactive forms, lazy loading, ng-icon setup, and Tailwind styling.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 27, 2026
developmenttypescriptgoreactangularapifrontend

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 3 files and shows the line behind each finding

Scanned September 27, 2026

npx -y skills add David-Li0406/meta-skill-evloving --skill angular-best-practices --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Angular Best Practices?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Angular Best Practices
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/david-li0406-angular-best-practices/badge)](https://www.skillsdirectory.com/skills/david-li0406-angular-best-practices)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: angular-best-practices
description: Angular 21 development with modern best practices including signals, standalone components, reactive patterns, and accessibility. Use when creating Angular components, services, templates, or performing any Angular frontend development work. Covers TypeScript strict typing, signal-based state management, reactive forms, lazy loading, ng-icon setup, and Tailwind styling.
---

# Angular 21 Best Practices

## TypeScript

- Use strict type checking
- Prefer type inference when type is obvious
- Avoid `any`; use `unknown` when type is uncertain

## Components

- Always use standalone components (do NOT set `standalone: true` — it's the default in v20+)
- Set `changeDetection: ChangeDetectionStrategy.OnPush`
- Use `input()` and `output()` functions instead of decorators
- Use `computed()` for derived state
- Keep components small and single-responsibility
- Prefer inline templates for small components
- Use Reactive forms over Template-driven
- Use `class` bindings instead of `ngClass`
- Use `style` bindings instead of `ngStyle`
- For external templates/styles, use paths relative to the component TS file
- Do NOT use `@HostBinding`/`@HostListener` — use the `host` object in the decorator instead

## State Management with Signals

- Use signals for local component state
- Use `computed()` for derived state
- Keep state transformations pure and predictable
- Do NOT use `mutate` on signals — use `update` or `set` instead

For complex derived state patterns, see [references/signal-patterns.md](references/signal-patterns.md).

## Resources (Async Data)

Use `resource()` for async data fetching with signals:

```typescript
const userResource = resource({
  params: () => ({ id: userId() }),
  loader: ({ params, abortSignal }) => fetch(`/api/users/${params.id}`, { signal: abortSignal }),
});

const userName = computed(() => userResource.hasValue() ? userResource.value().name : undefined);
```

Key `resource` patterns:
- `params` returns `undefined` → loader doesn't run, status becomes `'idle'`
- Use `abortSignal` to cancel in-flight requests
- Check `hasValue()` before accessing `value()` to handle loading/error states
- Status values: `'idle'`, `'loading'`, `'reloading'`, `'resolved'`, `'error'`, `'local'`

## Templates

- Use native control flow: `@if`, `@for`, `@switch` (NOT `*ngIf`, `*ngFor`, `*ngSwitch`)
- Use async pipe for observables
- Keep templates simple — no complex logic
- Do NOT use arrow functions in templates (not supported)
- Do NOT assume globals like `new Date()` are available

## Services

- Single responsibility per service
- Use `providedIn: 'root'` for singletons
- Use `inject()` function instead of constructor injection

```typescript
@Injectable({ providedIn: 'root' })
export class UserService {
  private readonly http = inject(HttpClient);
}
```

## Routing

- Implement lazy loading for feature routes:

```typescript
export const routes: Routes = [
  {
    path: 'admin',
    loadComponent: () => import('./admin/admin.page').then(m => m.AdminPage),
  },
];
```

## File Naming

- Routable view components: `file-name.page.ts`, `file-name.page.html`, `file-name.page.css`
- Regular components: `file-name.component.ts`
- Services: `file-name.service.ts`

## Icons (ng-icon)

```typescript
import { NgIcon, provideIcons } from '@ng-icons/core';
import { heroSparkles, heroTrash } from '@ng-icons/heroicons/outline';

@Component({
  selector: 'app-example',
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [NgIcon],
  providers: [provideIcons({ heroSparkles, heroTrash })],
  template: `<ng-icon name="heroSparkles" />`,
})
export class ExampleComponent {}
```

## Images

- Use `NgOptimizedImage` for all static images
- `NgOptimizedImage` does NOT work for inline base64 images

## Styling

- Use Tailwind 4.1 for CSS (see tailwind skill if available)
- Angular CDK is available when needed

## Accessibility

- MUST pass all AXE checks
- MUST meet WCAG AA minimums: focus management, color contrast, ARIA attributes

Files in this skill

  • SKILL.md4 KB
  • angular-best-practices.skill4 KB
  • signal-patterns.md5.8 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…