[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6JB05Z34R9VDKZX0M4068B5":3,"skill-same:01M6JB05Z34R9VDKZX0M4068B5":70},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":38,"linkOnly":39,"markdownContent":40,"markdownBody":41,"frontMatter":42,"refName":43,"commitSha":44,"skillDirectory":45,"forksCount":13,"repositoryHtmlUrl":46,"repositoryHomepageUrl":6,"ownerHtmlUrl":47,"ownerBlogUrl":6,"ownerDescription":48,"updatedAt":49,"install":50,"resources":63},"01M6JB05Z34R9VDKZX0M4068B5","angular-20-standalone-component",null,"Create Angular 20 standalone components using modern patterns: Signals for state management, input()\u002Foutput() functions (not decorators), @if\u002F@for\u002F@switch control flow (not *ngIf\u002F*ngFor), inject() dependency injection (not constructor), and OnPush change detection. Use this skill when scaffolding new UI components that need reactive state, form handling, or integration with services following the three-layer architecture.","superhealth\u002Fskills-hub","superhealth","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F6292112?v=4","01M6JA6E7F21BYK5W3E4P270TT","01M6JA6EC0W8MPHKDJVBZDSEZ0",0,"MIT","https:\u002F\u002Fgithub.com\u002Fsuperhealth\u002Fskills-hub\u002Fblob\u002Fmaster\u002Fskills\u002F7spade\u002Fangular-20-standalone-component\u002FSKILL.md",[],[18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37],"component","standalone","angular","angular 20 standalone component","for","components","with","output","decorators","form","ui components","dependency injection","scaffolding","three","switch","functions","use","state","create","architecture","2026-11-10 10:12:30",false,"---\nname: angular-20-standalone-component\ndescription: \"Create Angular 20 standalone components using modern patterns: Signals for state management, input()\u002Foutput() functions (not decorators), @if\u002F@for\u002F@switch control flow (not *ngIf\u002F*ngFor), inject() dependency injection (not constructor), and OnPush change detection. Use this skill when scaffolding new UI components that need reactive state, form handling, or integration with services following the three-layer architecture.\"\nlicense: \"MIT\"\n---\n\n# Angular 20 Standalone Component Skill\n\nThis skill helps create Angular 20 components following modern patterns and project standards.\n\n## Core Principles\n\n### Modern Angular 20 Patterns\n- **Standalone Components**: 100% standalone, zero NgModules\n- **Signals**: Use `signal()`, `computed()`, `effect()` for state\n- **New Syntax**: `input()`, `output()`, `@if`, `@for`, `@switch`\n- **inject()**: Function-based dependency injection\n- **OnPush**: Change detection strategy for performance\n\n### Architecture Integration\n- **Presentation Layer**: Components handle UI only\n- **Service Integration**: Inject services for business logic\n- **No Direct Repository**: Never inject repositories directly\n- **Event-Driven**: Use EventBus for cross-module communication\n\n## Component Template\n\n```typescript\nimport { Component, signal, computed, effect, input, output, inject, ChangeDetectionStrategy } from '@angular\u002Fcore';\nimport { SHARED_IMPORTS } from '@shared';\nimport { YourService } from '@core\u002Fservices\u002Fyour.service';\n\n@Component({\n  selector: 'app-your-component',\n  standalone: true,\n  imports: [SHARED_IMPORTS],\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  template: `\n    \u003Cdiv class=\"component-container\">\n      @if (loading()) {\n        \u003Cnz-spin nzSimple \u002F>\n      } @else if (hasError()) {\n        \u003Cnz-alert \n          nzType=\"error\" \n          [nzMessage]=\"errorMessage()!\"\n          nzShowIcon\n        \u002F>\n      } @else {\n        \u003Cdiv class=\"content\">\n          @for (item of items(); track item.id) {\n            \u003Capp-item-card \n              [item]=\"item\"\n              (itemChange)=\"handleItemChange($event)\"\n            \u002F>\n          } @empty {\n            \u003Cnz-empty nzNotFoundContent=\"No items found\" \u002F>\n          }\n        \u003C\u002Fdiv>\n      }\n    \u003C\u002Fdiv>\n  `,\n  styles: [`\n    .component-container {\n      padding: 24px;\n    }\n    \n    .content {\n      display: grid;\n      gap: 16px;\n    }\n  `]\n})\nexport class YourComponent {\n  \u002F\u002F ✅ Inject services with inject()\n  private yourService = inject(YourService);\n  \n  \u002F\u002F ✅ Use input() for properties (NOT @Input())\n  blueprintId = input.required\u003Cstring>();\n  readonly = input(false);\n  \n  \u002F\u002F ✅ Use output() for events (NOT @Output())\n  itemChange = output\u003CItem>();\n  \n  \u002F\u002F ✅ Use signal() for mutable state\n  loading = signal(false);\n  error = signal\u003Cstring | null>(null);\n  items = signal\u003CItem[]>([]);\n  \n  \u002F\u002F ✅ Use computed() for derived state\n  hasError = computed(() => this.error() !== null);\n  errorMessage = computed(() => this.error());\n  totalItems = computed(() => this.items().length);\n  \n  \u002F\u002F ✅ Use effect() for side effects\n  constructor() {\n    effect(() => {\n      const id = this.blueprintId();\n      console.log('Blueprint ID changed:', id);\n      this.loadItems(id);\n    });\n  }\n  \n  ngOnInit(): void {\n    this.loadItems(this.blueprintId());\n  }\n  \n  async loadItems(blueprintId: string): Promise\u003Cvoid> {\n    this.loading.set(true);\n    this.error.set(null);\n    \n    try {\n      const items = await this.yourService.getItems(blueprintId);\n      this.items.set(items);\n    } catch (err) {\n      this.error.set(err instanceof Error ? err.message : 'Unknown error');\n    } finally {\n      this.loading.set(false);\n    }\n  }\n  \n  handleItemChange(item: Item): void {\n    \u002F\u002F Update local state\n    this.items.update(items => \n      items.map(i => i.id === item.id ? item : i)\n    );\n    \n    \u002F\u002F Emit to parent\n    this.itemChange.emit(item);\n  }\n}\n```\n\n## Key Patterns\n\n### 1. Signal State Management\n\n```typescript\n\u002F\u002F Writable signals\nprivate _items = signal\u003CItem[]>([]);\n\n\u002F\u002F Read-only public access\nitems = this._items.asReadonly();\n\n\u002F\u002F Computed derived state\nfilteredItems = computed(() => \n  this._items().filter(item => item.status === 'active')\n);\n\n\u002F\u002F Update signals\nthis._items.set([...]); \u002F\u002F Replace\nthis._items.update(items => [...items, newItem]); \u002F\u002F Transform\n```\n\n### 2. Control Flow Syntax\n\n```typescript\n\u002F\u002F ✅ CORRECT: New @if syntax\n@if (condition()) {\n  \u003Cdiv>Content\u003C\u002Fdiv>\n} @else if (otherCondition()) {\n  \u003Cdiv>Other\u003C\u002Fdiv>\n} @else {\n  \u003Cdiv>Default\u003C\u002Fdiv>\n}\n\n\u002F\u002F ✅ CORRECT: New @for syntax with track\n@for (item of items(); track item.id) {\n  \u003Cdiv>{{ item.name }}\u003C\u002Fdiv>\n} @empty {\n  \u003Cp>No items\u003C\u002Fp>\n}\n\n\u002F\u002F ✅ CORRECT: New @switch syntax\n@switch (status()) {\n  @case ('active') { \u003Cspan class=\"badge-success\">Active\u003C\u002Fspan> }\n  @case ('inactive') { \u003Cspan class=\"badge-danger\">Inactive\u003C\u002Fspan> }\n  @default { \u003Cspan class=\"badge-default\">Unknown\u003C\u002Fspan> }\n}\n\n\u002F\u002F ❌ WRONG: Old syntax (forbidden)\n\u003Cdiv *ngIf=\"condition\">...\u003C\u002Fdiv>\n\u003Cdiv *ngFor=\"let item of items\">...\u003C\u002Fdiv>\n\u003Cdiv [ngSwitch]=\"status\">...\u003C\u002Fdiv>\n```\n\n### 3. Input\u002FOutput Functions\n\n```typescript\n\u002F\u002F ✅ CORRECT: Use input()\u002Foutput() functions\ntask = input.required\u003CTask>();\nreadonly = input(false);\ntaskChange = output\u003CTask>();\n\n\u002F\u002F ❌ WRONG: Decorators (forbidden)\n@Input() task!: Task;\n@Output() taskChange = new EventEmitter\u003CTask>();\n```\n\n### 4. Dependency Injection\n\n```typescript\n\u002F\u002F ✅ CORRECT: Use inject()\nprivate taskService = inject(TaskService);\nprivate router = inject(Router);\nprivate destroyRef = inject(DestroyRef);\n\n\u002F\u002F ❌ WRONG: Constructor injection (forbidden)\nconstructor(\n  private taskService: TaskService,\n  private router: Router\n) {}\n```\n\n### 5. Subscriptions\n\n```typescript\nimport { takeUntilDestroyed } from '@angular\u002Fcore\u002Frxjs-interop';\n\n\u002F\u002F ✅ CORRECT: Auto-cleanup with takeUntilDestroyed\nprivate destroyRef = inject(DestroyRef);\n\nngOnInit(): void {\n  this.service.data$\n    .pipe(takeUntilDestroyed(this.destroyRef))\n    .subscribe(data => this.items.set(data));\n}\n\n\u002F\u002F ❌ WRONG: Manual subscriptions without cleanup\nngOnInit(): void {\n  this.service.data$.subscribe(data => this.items.set(data));\n}\n```\n\n## Component Types\n\n### Smart Component (Container)\n\n```typescript\n@Component({\n  selector: 'app-task-list',\n  standalone: true,\n  imports: [SHARED_IMPORTS, TaskItemComponent],\n  template: `\n    @for (task of tasks(); track task.id) {\n      \u003Capp-task-item \n        [task]=\"task\"\n        (taskChange)=\"updateTask($event)\"\n      \u002F>\n    }\n  `\n})\nexport class TaskListComponent {\n  private taskService = inject(TaskService);\n  tasks = signal\u003CTask[]>([]);\n  \n  ngOnInit(): void {\n    this.loadTasks();\n  }\n  \n  async loadTasks(): Promise\u003Cvoid> {\n    const tasks = await this.taskService.getTasks();\n    this.tasks.set(tasks);\n  }\n  \n  async updateTask(task: Task): Promise\u003Cvoid> {\n    await this.taskService.updateTask(task.id, task);\n    this.tasks.update(tasks => \n      tasks.map(t => t.id === task.id ? task : t)\n    );\n  }\n}\n```\n\n### Presentational Component (Pure)\n\n```typescript\n@Component({\n  selector: 'app-task-item',\n  standalone: true,\n  imports: [SHARED_IMPORTS],\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  template: `\n    \u003Cnz-card>\n      \u003Ch3>{{ task().title }}\u003C\u002Fh3>\n      \u003Cp>{{ task().description }}\u003C\u002Fp>\n      \u003Cbutton nz-button (click)=\"handleComplete()\">\n        Complete\n      \u003C\u002Fbutton>\n    \u003C\u002Fnz-card>\n  `\n})\nexport class TaskItemComponent {\n  task = input.required\u003CTask>();\n  taskChange = output\u003CTask>();\n  \n  handleComplete(): void {\n    const updated = { ...this.task(), status: 'completed' };\n    this.taskChange.emit(updated);\n  }\n}\n```\n\n## Form Handling\n\n```typescript\nimport { FormBuilder, FormGroup, Validators } from '@angular\u002Fforms';\n\n@Component({\n  selector: 'app-task-form',\n  standalone: true,\n  imports: [SHARED_IMPORTS, ReactiveFormsModule],\n  template: `\n    \u003Cform nz-form [formGroup]=\"form\" (ngSubmit)=\"handleSubmit()\">\n      \u003Cnz-form-item>\n        \u003Cnz-form-label nzRequired>Title\u003C\u002Fnz-form-label>\n        \u003Cnz-form-control nzErrorTip=\"Please enter task title\">\n          \u003Cinput nz-input formControlName=\"title\" \u002F>\n        \u003C\u002Fnz-form-control>\n      \u003C\u002Fnz-form-item>\n      \n      \u003Cbutton nz-button nzType=\"primary\" [disabled]=\"!form.valid\">\n        Submit\n      \u003C\u002Fbutton>\n    \u003C\u002Fform>\n  `\n})\nexport class TaskFormComponent {\n  private fb = inject(FormBuilder);\n  \n  form = this.fb.group({\n    title: ['', [Validators.required, Validators.maxLength(200)]],\n    description: [''],\n    status: ['pending']\n  });\n  \n  taskSubmit = output\u003CPartial\u003CTask>>();\n  \n  handleSubmit(): void {\n    if (this.form.valid) {\n      this.taskSubmit.emit(this.form.value);\n      this.form.reset();\n    }\n  }\n}\n```\n\n## Checklist\n\nWhen creating a component:\n\n- [ ] Standalone component with imports\n- [ ] Uses signal() for state\n- [ ] Uses computed() for derived state\n- [ ] Uses input()\u002Foutput() functions\n- [ ] Uses @if\u002F@for\u002F@switch syntax\n- [ ] Uses inject() for dependencies\n- [ ] OnPush change detection\n- [ ] No business logic in component\n- [ ] Proper error handling\n- [ ] Loading states\n- [ ] Empty states\n- [ ] TypeScript strict typing\n\n## References\n\n- [Angular Instructions](.github\u002Finstructions\u002Fangular.instructions.md)\n- [Signals State Management](.github\u002Finstructions\u002Fng-ng-events(GigHub)-signals-state.instructions.md)\n- [Architecture Guide](.github\u002Finstructions\u002Fng-ng-events(GigHub)-architecture.instructions.md)\n","# Angular 20 Standalone Component Skill\n\nThis skill helps create Angular 20 components following modern patterns and project standards.\n\n## Core Principles\n\n### Modern Angular 20 Patterns\n- **Standalone Components**: 100% standalone, zero NgModules\n- **Signals**: Use `signal()`, `computed()`, `effect()` for state\n- **New Syntax**: `input()`, `output()`, `@if`, `@for`, `@switch`\n- **inject()**: Function-based dependency injection\n- **OnPush**: Change detection strategy for performance\n\n### Architecture Integration\n- **Presentation Layer**: Components handle UI only\n- **Service Integration**: Inject services for business logic\n- **No Direct Repository**: Never inject repositories directly\n- **Event-Driven**: Use EventBus for cross-module communication\n\n## Component Template\n\n```typescript\nimport { Component, signal, computed, effect, input, output, inject, ChangeDetectionStrategy } from '@angular\u002Fcore';\nimport { SHARED_IMPORTS } from '@shared';\nimport { YourService } from '@core\u002Fservices\u002Fyour.service';\n\n@Component({\n  selector: 'app-your-component',\n  standalone: true,\n  imports: [SHARED_IMPORTS],\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  template: `\n    \u003Cdiv class=\"component-container\">\n      @if (loading()) {\n        \u003Cnz-spin nzSimple \u002F>\n      } @else if (hasError()) {\n        \u003Cnz-alert \n          nzType=\"error\" \n          [nzMessage]=\"errorMessage()!\"\n          nzShowIcon\n        \u002F>\n      } @else {\n        \u003Cdiv class=\"content\">\n          @for (item of items(); track item.id) {\n            \u003Capp-item-card \n              [item]=\"item\"\n              (itemChange)=\"handleItemChange($event)\"\n            \u002F>\n          } @empty {\n            \u003Cnz-empty nzNotFoundContent=\"No items found\" \u002F>\n          }\n        \u003C\u002Fdiv>\n      }\n    \u003C\u002Fdiv>\n  `,\n  styles: [`\n    .component-container {\n      padding: 24px;\n    }\n    \n    .content {\n      display: grid;\n      gap: 16px;\n    }\n  `]\n})\nexport class YourComponent {\n  \u002F\u002F ✅ Inject services with inject()\n  private yourService = inject(YourService);\n  \n  \u002F\u002F ✅ Use input() for properties (NOT @Input())\n  blueprintId = input.required\u003Cstring>();\n  readonly = input(false);\n  \n  \u002F\u002F ✅ Use output() for events (NOT @Output())\n  itemChange = output\u003CItem>();\n  \n  \u002F\u002F ✅ Use signal() for mutable state\n  loading = signal(false);\n  error = signal\u003Cstring | null>(null);\n  items = signal\u003CItem[]>([]);\n  \n  \u002F\u002F ✅ Use computed() for derived state\n  hasError = computed(() => this.error() !== null);\n  errorMessage = computed(() => this.error());\n  totalItems = computed(() => this.items().length);\n  \n  \u002F\u002F ✅ Use effect() for side effects\n  constructor() {\n    effect(() => {\n      const id = this.blueprintId();\n      console.log('Blueprint ID changed:', id);\n      this.loadItems(id);\n    });\n  }\n  \n  ngOnInit(): void {\n    this.loadItems(this.blueprintId());\n  }\n  \n  async loadItems(blueprintId: string): Promise\u003Cvoid> {\n    this.loading.set(true);\n    this.error.set(null);\n    \n    try {\n      const items = await this.yourService.getItems(blueprintId);\n      this.items.set(items);\n    } catch (err) {\n      this.error.set(err instanceof Error ? err.message : 'Unknown error');\n    } finally {\n      this.loading.set(false);\n    }\n  }\n  \n  handleItemChange(item: Item): void {\n    \u002F\u002F Update local state\n    this.items.update(items => \n      items.map(i => i.id === item.id ? item : i)\n    );\n    \n    \u002F\u002F Emit to parent\n    this.itemChange.emit(item);\n  }\n}\n```\n\n## Key Patterns\n\n### 1. Signal State Management\n\n```typescript\n\u002F\u002F Writable signals\nprivate _items = signal\u003CItem[]>([]);\n\n\u002F\u002F Read-only public access\nitems = this._items.asReadonly();\n\n\u002F\u002F Computed derived state\nfilteredItems = computed(() => \n  this._items().filter(item => item.status === 'active')\n);\n\n\u002F\u002F Update signals\nthis._items.set([...]); \u002F\u002F Replace\nthis._items.update(items => [...items, newItem]); \u002F\u002F Transform\n```\n\n### 2. Control Flow Syntax\n\n```typescript\n\u002F\u002F ✅ CORRECT: New @if syntax\n@if (condition()) {\n  \u003Cdiv>Content\u003C\u002Fdiv>\n} @else if (otherCondition()) {\n  \u003Cdiv>Other\u003C\u002Fdiv>\n} @else {\n  \u003Cdiv>Default\u003C\u002Fdiv>\n}\n\n\u002F\u002F ✅ CORRECT: New @for syntax with track\n@for (item of items(); track item.id) {\n  \u003Cdiv>{{ item.name }}\u003C\u002Fdiv>\n} @empty {\n  \u003Cp>No items\u003C\u002Fp>\n}\n\n\u002F\u002F ✅ CORRECT: New @switch syntax\n@switch (status()) {\n  @case ('active') { \u003Cspan class=\"badge-success\">Active\u003C\u002Fspan> }\n  @case ('inactive') { \u003Cspan class=\"badge-danger\">Inactive\u003C\u002Fspan> }\n  @default { \u003Cspan class=\"badge-default\">Unknown\u003C\u002Fspan> }\n}\n\n\u002F\u002F ❌ WRONG: Old syntax (forbidden)\n\u003Cdiv *ngIf=\"condition\">...\u003C\u002Fdiv>\n\u003Cdiv *ngFor=\"let item of items\">...\u003C\u002Fdiv>\n\u003Cdiv [ngSwitch]=\"status\">...\u003C\u002Fdiv>\n```\n\n### 3. Input\u002FOutput Functions\n\n```typescript\n\u002F\u002F ✅ CORRECT: Use input()\u002Foutput() functions\ntask = input.required\u003CTask>();\nreadonly = input(false);\ntaskChange = output\u003CTask>();\n\n\u002F\u002F ❌ WRONG: Decorators (forbidden)\n@Input() task!: Task;\n@Output() taskChange = new EventEmitter\u003CTask>();\n```\n\n### 4. Dependency Injection\n\n```typescript\n\u002F\u002F ✅ CORRECT: Use inject()\nprivate taskService = inject(TaskService);\nprivate router = inject(Router);\nprivate destroyRef = inject(DestroyRef);\n\n\u002F\u002F ❌ WRONG: Constructor injection (forbidden)\nconstructor(\n  private taskService: TaskService,\n  private router: Router\n) {}\n```\n\n### 5. Subscriptions\n\n```typescript\nimport { takeUntilDestroyed } from '@angular\u002Fcore\u002Frxjs-interop';\n\n\u002F\u002F ✅ CORRECT: Auto-cleanup with takeUntilDestroyed\nprivate destroyRef = inject(DestroyRef);\n\nngOnInit(): void {\n  this.service.data$\n    .pipe(takeUntilDestroyed(this.destroyRef))\n    .subscribe(data => this.items.set(data));\n}\n\n\u002F\u002F ❌ WRONG: Manual subscriptions without cleanup\nngOnInit(): void {\n  this.service.data$.subscribe(data => this.items.set(data));\n}\n```\n\n## Component Types\n\n### Smart Component (Container)\n\n```typescript\n@Component({\n  selector: 'app-task-list',\n  standalone: true,\n  imports: [SHARED_IMPORTS, TaskItemComponent],\n  template: `\n    @for (task of tasks(); track task.id) {\n      \u003Capp-task-item \n        [task]=\"task\"\n        (taskChange)=\"updateTask($event)\"\n      \u002F>\n    }\n  `\n})\nexport class TaskListComponent {\n  private taskService = inject(TaskService);\n  tasks = signal\u003CTask[]>([]);\n  \n  ngOnInit(): void {\n    this.loadTasks();\n  }\n  \n  async loadTasks(): Promise\u003Cvoid> {\n    const tasks = await this.taskService.getTasks();\n    this.tasks.set(tasks);\n  }\n  \n  async updateTask(task: Task): Promise\u003Cvoid> {\n    await this.taskService.updateTask(task.id, task);\n    this.tasks.update(tasks => \n      tasks.map(t => t.id === task.id ? task : t)\n    );\n  }\n}\n```\n\n### Presentational Component (Pure)\n\n```typescript\n@Component({\n  selector: 'app-task-item',\n  standalone: true,\n  imports: [SHARED_IMPORTS],\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  template: `\n    \u003Cnz-card>\n      \u003Ch3>{{ task().title }}\u003C\u002Fh3>\n      \u003Cp>{{ task().description }}\u003C\u002Fp>\n      \u003Cbutton nz-button (click)=\"handleComplete()\">\n        Complete\n      \u003C\u002Fbutton>\n    \u003C\u002Fnz-card>\n  `\n})\nexport class TaskItemComponent {\n  task = input.required\u003CTask>();\n  taskChange = output\u003CTask>();\n  \n  handleComplete(): void {\n    const updated = { ...this.task(), status: 'completed' };\n    this.taskChange.emit(updated);\n  }\n}\n```\n\n## Form Handling\n\n```typescript\nimport { FormBuilder, FormGroup, Validators } from '@angular\u002Fforms';\n\n@Component({\n  selector: 'app-task-form',\n  standalone: true,\n  imports: [SHARED_IMPORTS, ReactiveFormsModule],\n  template: `\n    \u003Cform nz-form [formGroup]=\"form\" (ngSubmit)=\"handleSubmit()\">\n      \u003Cnz-form-item>\n        \u003Cnz-form-label nzRequired>Title\u003C\u002Fnz-form-label>\n        \u003Cnz-form-control nzErrorTip=\"Please enter task title\">\n          \u003Cinput nz-input formControlName=\"title\" \u002F>\n        \u003C\u002Fnz-form-control>\n      \u003C\u002Fnz-form-item>\n      \n      \u003Cbutton nz-button nzType=\"primary\" [disabled]=\"!form.valid\">\n        Submit\n      \u003C\u002Fbutton>\n    \u003C\u002Fform>\n  `\n})\nexport class TaskFormComponent {\n  private fb = inject(FormBuilder);\n  \n  form = this.fb.group({\n    title: ['', [Validators.required, Validators.maxLength(200)]],\n    description: [''],\n    status: ['pending']\n  });\n  \n  taskSubmit = output\u003CPartial\u003CTask>>();\n  \n  handleSubmit(): void {\n    if (this.form.valid) {\n      this.taskSubmit.emit(this.form.value);\n      this.form.reset();\n    }\n  }\n}\n```\n\n## Checklist\n\nWhen creating a component:\n\n- [ ] Standalone component with imports\n- [ ] Uses signal() for state\n- [ ] Uses computed() for derived state\n- [ ] Uses input()\u002Foutput() functions\n- [ ] Uses @if\u002F@for\u002F@switch syntax\n- [ ] Uses inject() for dependencies\n- [ ] OnPush change detection\n- [ ] No business logic in component\n- [ ] Proper error handling\n- [ ] Loading states\n- [ ] Empty states\n- [ ] TypeScript strict typing\n\n## References\n\n- [Angular Instructions](.github\u002Finstructions\u002Fangular.instructions.md)\n- [Signals State Management](.github\u002Finstructions\u002Fng-ng-events(GigHub)-signals-state.instructions.md)\n- [Architecture Guide](.github\u002Finstructions\u002Fng-ng-events(GigHub)-architecture.instructions.md)\n",{"name":5,"license":14,"description":7},"master","08cc2532077058aa50e6e18f54695bc256c88152","skills\u002F7spade\u002Fangular-20-standalone-component","https:\u002F\u002Fgithub.com\u002Fsuperhealth\u002Fskills-hub","https:\u002F\u002Fgithub.com\u002Fsuperhealth","java engineer","2026-04-06 22:07:23",{"source":8,"skillName":5,"commands":51,"prompt":61,"zipAvailable":62},[52,55,58],{"tool":53,"command":54},"npx","npx skills add superhealth\u002Fskills-hub --skill angular-20-standalone-component",{"tool":56,"command":57},"bunx","bunx skills add superhealth\u002Fskills-hub --skill angular-20-standalone-component",{"tool":59,"command":60},"pnpm","pnpm dlx skills add superhealth\u002Fskills-hub --skill angular-20-standalone-component","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fsuperhealth\u002Fskills-hub\u002Fblob\u002Fmaster\u002Fskills\u002F7spade\u002Fangular-20-standalone-component\u002FSKILL.md",true,[64],{"path":65,"resourceType":66,"resourceTypeDesc":67,"sizeBytes":68,"sourceHtmlUrl":69},"skill-report.json","REFERENCE","参考文档",12863,"https:\u002F\u002Fgithub.com\u002Fsuperhealth\u002Fskills-hub\u002Fblob\u002Fmaster\u002Fskills\u002F7spade\u002Fangular-20-standalone-component\u002Fskill-report.json",[71,102,127,140,154,178],{"skillNo":72,"name":73,"nameZh":6,"description":74,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":75,"categories":76,"keywords":82,"publishedAt":38},"01M6MC9F3WHV8S8FZ2W4TRB0FE","vercel-react-best-practices","React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React\u002FNext.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.","https:\u002F\u002Fgithub.com\u002Fsuperhealth\u002Fskills-hub\u002Fblob\u002Fmaster\u002Fskills\u002Fzhanlincui\u002Fvercel-react-best-practices\u002FSKILL.md",[77],{"categoryNo":78,"categoryName":79,"taxonomyType":80,"taxonomyTypeDesc":81},"01JBSEEDCAT000000000000009","前端开发","SCENARIO","使用场景",[83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,23,100,101],"react","vercel react best practices","best practices","vercel","react best practices","data fetching","code","triggers","pages","next","patterns","refactoring","data","Optimization","tasks","guidelines","react components","performance","writing",{"skillNo":103,"name":104,"nameZh":6,"description":105,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":106,"categories":107,"keywords":112,"publishedAt":38},"01M6MB8KWE1Q5A5KERR7RFTQWP","vue-testing-best-practices","Use for Vue.js testing. Covers Vitest, Vue Test Utils, component testing, mocking, testing patterns, and Playwright for E2E testing.","https:\u002F\u002Fgithub.com\u002Fsuperhealth\u002Fskills-hub\u002Fblob\u002Fmaster\u002Fskills\u002Fvuejs-ai\u002Fvue-testing-best-practices\u002FSKILL.md",[108,111],{"categoryNo":109,"categoryName":110,"taxonomyType":80,"taxonomyTypeDesc":81},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":78,"categoryName":79,"taxonomyType":80,"taxonomyTypeDesc":81},[113,114,115,85,116,117,118,119,120,34,18,93,121,122,22,123,124,125,126],"vue testing best practices","testing best practices","vue","testing","testing patterns","js","e2e","vitest","test","mocking","utils","e2e testing","github","playwright",{"skillNo":128,"name":129,"nameZh":6,"description":130,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":131,"categories":132,"keywords":134,"publishedAt":38},"01M6MB8GK06M6GA4KVYNDV1BZP","vue-router-best-practices","Vue Router 4 patterns, navigation guards, route params, and route-component lifecycle interactions.","https:\u002F\u002Fgithub.com\u002Fsuperhealth\u002Fskills-hub\u002Fblob\u002Fmaster\u002Fskills\u002Fvuejs-ai\u002Fvue-router-best-practices\u002FSKILL.md",[133],{"categoryNo":78,"categoryName":79,"taxonomyType":80,"taxonomyTypeDesc":81},[85,115,135,136,137,93,138,139,18,125],"router","vue router best practices","route","navigation","lifecycle",{"skillNo":141,"name":142,"nameZh":6,"description":143,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":144,"categories":145,"keywords":147,"publishedAt":38},"01M6MB8DQF21TZMQ9XC3745ERW","vue-pinia-best-practices","Pinia stores, state management patterns, store setup, and reactivity with stores.","https:\u002F\u002Fgithub.com\u002Fsuperhealth\u002Fskills-hub\u002Fblob\u002Fmaster\u002Fskills\u002Fvuejs-ai\u002Fvue-pinia-best-practices\u002FSKILL.md",[146],{"categoryNo":78,"categoryName":79,"taxonomyType":80,"taxonomyTypeDesc":81},[148,149,115,85,24,150,93,151,35,152,153,125],"vue pinia best practices","pinia","store","management","state management","setup",{"skillNo":155,"name":156,"nameZh":6,"description":157,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":158,"categories":159,"keywords":169,"publishedAt":38},"01M6MB8A7MC08747J9TV4GWQ9A","vue-options-api-best-practices","Vue 3 Options API style (data(), methods, this context). Each reference shows Options API solution only.","https:\u002F\u002Fgithub.com\u002Fsuperhealth\u002Fskills-hub\u002Fblob\u002Fmaster\u002Fskills\u002Fvuejs-ai\u002Fvue-options-api-best-practices\u002FSKILL.md",[160,161,164],{"categoryNo":78,"categoryName":79,"taxonomyType":80,"taxonomyTypeDesc":81},{"categoryNo":162,"categoryName":163,"taxonomyType":80,"taxonomyTypeDesc":81},"01JBSEEDCAT000000000000010","后端与接口",{"categoryNo":165,"categoryName":166,"taxonomyType":167,"taxonomyTypeDesc":168},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[115,170,171,172,85,173,174,175,176,95,125,177],"options","vue options api best practices","api","methods","reference","only","context","style",{"skillNo":179,"name":180,"nameZh":6,"description":181,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":182,"categories":183,"keywords":185,"publishedAt":38},"01M6MB85ZTQC24Q04X49MM4YXN","vue-development-guides","A collection of best practices and tips for developing applications using Vue.js. This skill MUST be apply when developing, refactoring or reviewing Vue.js or Nuxt projects.","https:\u002F\u002Fgithub.com\u002Fsuperhealth\u002Fskills-hub\u002Fblob\u002Fmaster\u002Fskills\u002Fvuejs-ai\u002Fvue-development-guides\u002FSKILL.md",[184],{"categoryNo":78,"categoryName":79,"taxonomyType":80,"taxonomyTypeDesc":81},[186,115,187,188,125,189,190,22,191,192,193,118,94,194,195,85],"development","guides","vue development guides","tips","apply","project","nuxt","projects","collection","applications"]