← Back to list

angular-development
by joseaplwork
⭐ 0🍴 0📅 Jan 18, 2026
SKILL.md
name: Angular Development description: Angular component patterns, dependency injection, reactive forms, and template best practices for the admin app.
Angular Development
This skill provides Angular-specific patterns and best practices for the admin application.
When to Use
- When creating or modifying Angular components in
apps/admin/ - When working with reactive forms
- When making HTTP requests
- When implementing dialogs or modals
- When managing component state
Component Guidelines
Component Structure
- Component selectors should use kebab-case
- Component selectors should have prefix
apporja - Class suffixes (
Component,Service) are optional - Use Angular Material components where applicable
- Always create component templates in separate HTML files
Example
@Component({
selector: 'app-participant-list',
templateUrl: './participant-list.html',
imports: [CommonModule, MatTableModule],
})
export class ParticipantList {
// Component code
}
Dependency Injection
Use inject() function instead of constructor injection. Prefix private injected services with underscore.
Example
export class ParticipantService {
private readonly _http = inject(HttpClient)
private readonly _config = inject(Config)
private readonly _snackbar = inject(Snackbar)
}
State Management
Use Angular signals for reactive state:
- Use
signal()for local component state - Emit state changes through dedicated state services
- Use
computed()for derived state
Example
export class ParticipantState {
private readonly _participants = signal<Participant[]>([])
readonly participants = this._participants.asReadonly()
emitParticipantCreated(participant: Participant): void {
this._participants.update(participants => [...participants, participant])
}
}
Reactive Forms
FormBuilder Usage
- Use
FormBuilderfor creating forms - Wrap FormArray items in FormControl instances
- Use
nonNullableforms when appropriate
Correct FormArray Initialization
// Good: FormArray with FormControl instances
form = this._fb.group({
roles: this._fb.array(
this.data.admin.roles.map(role => this._fb.control(role)),
[Validators.required],
),
})
// Bad: Raw values in FormArray
form = this._fb.group({
roles: this._fb.array(['admin'], [Validators.required]),
})
HTTP Requests
Best Practices
- Use
firstValueFrom()to convert observables to promises - Match HTTP verbs to backend endpoints (GET, POST, PATCH, DELETE)
- Map frontend field names to API field names in services
Example
update(id: string, payload: UpdatePayload): Promise<Participant> {
const apiPayload = {
name: payload.name,
phone: payload.phoneNumber, // Map frontend to API field
}
return firstValueFrom(
this._http.patch<Participant>(`${this._config.api.url}/participant/${id}`, apiPayload),
)
}
Dialog Patterns
Dialog Data Injection
- Inject
MAT_DIALOG_DATAto receive dialog data - Pass
handleSubmitcallbacks through dialog data - Use try-finally to handle submitting state
Example
interface DialogData {
handleSubmit: (payload: Payload) => Promise<void>
}
export class CreateDialog {
readonly data = inject<DialogData>(MAT_DIALOG_DATA)
private readonly _dialogRef = inject(MatDialogRef<CreateDialog>)
submitting = signal(false)
async onSubmit(): Promise<void> {
if (this.form.invalid || this.submitting()) return
this.submitting.set(true)
try {
const payload = this.form.value
await this.data.handleSubmit(payload)
this._dialogRef.close()
} finally {
this.submitting.set(false)
}
}
}
Template Best Practices
- Avoid duplicate event handlers (e.g., both
ngSubmitand buttonclick) - Match
formControlNameto form control definitions exactly - Use
trackwith unique values in@forloops
Example
<!-- Good: Single event handler -->
<form [formGroup]="form">
<button type="button" (click)="handleSubmit()">Submit</button>
</form>
<!-- Bad: Duplicate handlers -->
<form [formGroup]="form" (ngSubmit)="handleSubmit()">
<button type="submit" (click)="handleSubmit()">Submit</button>
</form>
Instructions
- Components: Use separate template files, kebab-case selectors with
apporjaprefix - Dependency injection: Use
inject()function, prefix private services with underscore - Forms: Always wrap FormArray items in FormControl instances
- HTTP: Use
firstValueFrom(), match HTTP verbs to backend, map field names - Dialogs: Inject
MAT_DIALOG_DATA, use try-finally for state management - Templates: Avoid duplicate event handlers, match form control names exactly
Score
Total Score
50/100
Based on repository quality metrics
✓SKILL.md
SKILL.mdファイルが含まれている
+20
○LICENSE
ライセンスが設定されている
0/10
○説明文
100文字以上の説明がある
0/10
○人気
GitHub Stars 100以上
0/15
○最近の活動
3ヶ月以内に更新がある
0/10
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
○タグ
1つ以上のタグが設定されている
0/5
Reviews
💬
Reviews coming soon