Skip to main content

angular

Angular 21.x core patterns and APIs — Signals, Standalone components, Zoneless change detection, SSR/Hydration, Dependency Injection, Component composition, Signal-based state, Testing. Load when writing Angular code for API reference, testing patterns, or SSR configuration.

소스 정보

저장소
kumaran-is/claude-code-onboarding
최근 소스 활동
2026년 5월 7일 18:07
감지된 SKILL.md 언어
영어
스타
36
포크
21

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

파일 탐색기
6 개 파일

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
angular
description
Angular 21.x core patterns and APIs — Signals, Standalone components, Zoneless change detection, SSR/Hydration, Dependency Injection, Component composition, Signal-based state, Testing. Load when writing Angular code for API reference, testing patterns, or SSR configuration.
allowed-tools
Read, Edit, Write, Glob, Grep, Bash, WebFetch, mcp__context7__resolve-library-id, mcp__context7__query-docs, mcp__angular-cli__get_best_practices, mcp__angular-cli__search_documentation
metadata
{"triggers":"Angular signals, Angular standalone, Angular zoneless, Angular SSR, Angular hydration, Angular DI, Angular testing, Angular state management, Angular 21","related-skills":"angular-spa, angular-best-practices, angular-ui-patterns","domain":"frontend","role":"specialist","scope":"reference","output-format":"code"}
last-reviewed
2026-03-15
## Iron Law **READ `angular-spa` skill for TailwindCSS 4.x, daisyUI 5.5.5, and workspace conventions BEFORE implementing. This skill is API reference only — no design token or styling patterns here.** ## When to Use This Skill - Building new Angular applications (v20+) - Implementing Signals-based reactive patterns - Creating Standalone Components and migrating from NgModules - Configuring Zoneless Angular applications - Implementing SSR, prerendering, and hydration - Optimizing Angular performance - Adopting modern Angular patterns and best practices ## Do Not Use This Skill When - Migrating from AngularJS (1.x) — use `angular-migration` skill - Working with legacy Angular apps that cannot upgrade - General TypeScript issues — use `typescript-expert` skill --- **Version context:** Angular 20 (Signals/Zoneless stable), Angular 21 (Signals-first default, Signal Forms available — current), Angular 22 (Signal Forms further enhancements). --- ## Angular 21 Zoneless Note Angular 21 is **zoneless by default**. Do NOT add `provideZonelessChangeDetection()` — it is implicit and adding it causes warnings. - Angular 20: `provideZonelessChangeDetection()` required explicitly - Angular 21+: Zoneless is the default. No provider needed. No `zone.js` import. This workspace uses Angular 21+. The patterns below show v20-style explicit providers for reference — in Angular 21 omit those providers. --- ## 1. Signals: The New Reactive Primitive Signals are Angular's fine-grained reactivity system, replacing zone.js-based change detection. ### Core signal / computed / effect ```typescript import { signal, computed, effect } from "@angular/core"; const count = signal(0); count.set(5); count.update((v) => v + 1); const doubled = computed(() => count() * 2); effect(() => { console.log(`Count changed to: ${count()}`); }); ``` ### Signal inputs, outputs, and model ```typescript import { Component, input, output, model } from "@angular/core"; @Component({ selector: "app-user-card", standalone: true, template: ` <div class="card"> <h3>{{ name() }}</h3> <span>{{ role() }}</span> <button (click)="select.emit(id())">Select</button> </div> `, }) export class UserCardComponent { id = input.required<string>(); name = input.required<string>(); role = input<string>("User"); select = output<string>(); isSelected = model(false); } // <app-user-card [id]="'123'" [name]="'John'" [(isSelected)]="selected" /> ``` Signal queries (viewChild, viewChildren, contentChild): See [references/signals-core.md](references/signals-core.md) --- ## 1b. linkedSignal — Derived Writable Signals `linkedSignal` creates a writable signal whose default resets when its source changes. | Use | Tool | |-----|------| | Derived read-only value | `computed()` | | Writable value that resets on source change | `linkedSignal()` | | Local state with no dependency | `signal()` | ```typescript import { signal, linkedSignal } from '@angular/core'; const items = signal(['a', 'b', 'c']); const selectedItem = linkedSignal(() => items()[0]); selectedItem.set('b'); // 'b' items.set(['x', 'y', 'z']); // selectedItem resets to 'x' ``` Full examples (advanced + pagination): [references/signals-core.md](references/signals-core.md) --- ## 1c. resource() — Reactive Async Data Fetching `resource()` is Angular's built-in reactive primitive for async data. | Scenario | Use | |----------|-----| | Component-local async data tied to signals | `resource()` | | Service-level shared HTTP calls | `HttpClient` + `inject()` | | Complex async pipelines (retry, cancel, merge) | `HttpClient` + RxJS | | One-time data loads | Either | ```typescript import { httpResource } from '@angular/common/http'; // HTTP GET shorthand — refetches when userId() changes userResource = httpResource<User>(() => `/api/users/${this.userId()}`); ``` Full API (resource() component, abort signal, status signals): [references/signals-core.md](references/signals-core.md) --- ## 1d. afterNextRender / afterRender — DOM Lifecycle Hooks In zoneless Angular 21, `afterNextRender` and `afterRender` replace `NgZone` lifecycle hacks for DOM-dependent initialization. Use these instead of `ngAfterViewInit` for code that requires a real DOM (chart init, third-party widget, scroll position). ```typescript import { Component, afterNextRender, afterRender, ElementRef, viewChild } from '@angular/core'; @Component({ selector: 'app-chart', template: '<canvas #canvas></canvas>' }) export class ChartComponent { canvas = viewChild.required<ElementRef<HTMLCanvasElement>>('canvas'); constructor() { // Runs once after the first render — DOM is guaranteed to exist afterNextRender(() => { initChart(this.canvas().nativeElement); }); // Runs after every render — use sparingly (performance cost) afterRender(() => { updateScrollPosition(); }); } } ``` **Rule:** Prefer `afterNextRender` over `afterRender` — it runs once. Both run in the browser only (SSR-safe). --- ## 1e. @let — Template Variable Declaration (Angular 18+) `@let` declares a local template variable — replaces the `*ngIf as` alias hack and verbose `ng-template` patterns. ```html <!-- Declare a local alias for a long expression --> @let user = currentUser(); @let greeting = 'Hello, ' + user.name + '!'; <h1>{{ greeting }}</h1> <p>{{ user.email }}</p> <!-- Useful with async resources --> @let data = userResource.value(); @if (data) { <app-user-profile [user]="data" /> } ``` **Rule:** Use `@let` to avoid repeating computed signal calls in templates. Do not use it as a substitute for `computed()` — `@let` re-evaluates on every render pass. --- ## 1f. Testing: Vitest (Stable in Angular 21) Angular 21 ships with **Vitest as the stable test runner** (replaces Karma). New projects default to Vitest. Migrate existing Karma setups. ```typescript // vitest.config.ts (Angular CLI generates this) import { defineConfig } from 'vitest/config'; import angular from '@analogjs/vite-plugin-angular'; export default defineConfig({ plugins: [angular()], test: { globals: true, environment: 'jsdom', setupFiles: ['src/test-setup.ts'], }, }); ``` ```typescript // Component test with zoneless TestBed import { TestBed } from '@angular/core/testing'; import { provideExperimentalZonelessChangeDetection } from '@angular/core'; beforeEach(() => { TestBed.configureTestingModule({ providers: [provideExperimentalZonelessChangeDetection()], imports: [MyComponent], }); }); ``` Run: `ng test` (uses Vitest by default in Angular 21 workspaces). See `reference/testing-vitest.md` for full patterns. --- ## 2. Standalone Components Standalone components are self-contained and don't require NgModule declarations. ### Creating Standalone Components ```typescript import { Component } from "@angular/core"; import { CommonModule } from "@angular/common"; import { RouterLink } from "@angular/router"; @Component({ // standalone: true is the default in Angular v20+ — omit it selector: "app-header", imports: [RouterLink], // CommonModule is a compat shim — don't import it template: ` <header> <a routerLink="/">Home</a> <a routerLink="/about">About</a> </header> `, }) export class HeaderComponent {} ``` ### Bootstrapping Without NgModule ```typescript // main.ts import { bootstrapApplication } from "@angular/platform-browser"; import { provideRouter } from "@angular/router"; import { provideHttpClient } from "@angular/common/http"; import { AppComponent } from "./app/app.component"; import { routes } from "./app/app.routes"; bootstrapApplication(AppComponent, { providers: [provideRouter(routes), provideHttpClient()], }); ``` ### Lazy Loading Standalone Components ```typescript export const routes: Routes = [ { path: "dashboard", loadComponent: () => import("./dashboard/dashboard.component").then((m) => m.DashboardComponent), }, { path: "admin", loadChildren: () => import("./admin/admin.routes").then((m) => m.ADMIN_ROUTES), }, ]; ``` --- ## 3. Zoneless Angular > **Angular 21 reminder:** Zoneless is the default. The `provideZonelessChangeDetection()` call below is v20-style — omit it in Angular 21 projects. ```typescript // main.ts (Angular 20 style — NOT needed in Angular 21+) bootstrapApplication(AppComponent, { providers: [provideZonelessChangeDetection()], }); ``` ### Zoneless Component Pattern ```typescript import { Component, signal, ChangeDetectionStrategy } from "@angular/core"; @Component({ selector: "app-counter", standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: ` <div>Count: {{ count() }}</div> <button (click)="increment()">+</button> `, }) export class CounterComponent { count = signal(0); increment() { this.count.update((v) => v + 1); } } ``` Benefits: no zone.js patches, cleaner stack traces, ~15KB bundle savings, better Web Component interop. --- ## 4. Server-Side Rendering & Hydration See [references/ssr-hydration.md](references/ssr-hydration.md) for SSR setup, hydration configuration, incremental hydration patterns, TransferState, and common SSR troubleshooting. --- ## 5. Modern Routing Patterns > See [references/api-reference.md](references/api-reference.md) for full routing examples (functional guards, resolvers). **Key patterns:** - `CanActivateFn` with `inject()` for functional guards - `ResolveFn<T>` for route-level data pre-fetching - `toSignal(route.data.pipe(...))` to consume resolved data --- ## 6. Dependency Injection > See [references/api-reference.md](references/api-reference.md) for full DI examples (inject(), InjectionToken). **Key patterns:** - `inject()` function (no constructor required) - `InjectionToken<T>` for typed configuration values --- ## 7. Component Composition > See [references/api-reference.md](references/api-reference.md) for full composition examples (ng-content slots, hostDirectives). **Key patterns:** - `<ng-content select="[attr]">` for named slots - `hostDirectives` for behavior composition without inheritance --- ## 8. Signal-Based State Management > See [references/api-reference.md](references/api-reference.md) for full state service and component store examples. **Key patterns:** - Private `signal()` + public `computed()` for encapsulated state - `@Injectable()` (no `providedIn: 'root'`) for scoped component stores --- ## 9. Forms with Signals > See [references/api-reference.md](references/api-reference.md) for full reactive forms and signal form patterns. **Key patterns:** - Signal Forms (preferred for Angular 21+) — see `signal-forms.md` reference below - `FormBuilder` + `Validators` for reactive forms (legacy, still supported) - Signal-based validation via `computed()` for derived validation state > **Angular 21+:** Prefer Signal Forms over reactive forms for new apps. See [`references/signal-forms.md`](references/signal-forms.md). --- ## 10. Performance Optimization ### Change Detection Strategies
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기