Agent skill
angular-component
Use when creating or modifying Angular components in WebV2 (Angular 19) with proper base class inheritance, state management, and platform patterns.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/angular-component-duc01226-easyplatform
SKILL.md
Angular Component Development
Required Reading
For comprehensive TypeScript/Angular patterns, you MUST read:
docs/claude/frontend-typescript-complete-guide.md- Complete patterns for components, stores, forms, API servicesdocs/claude/scss-styling-guide.md- SCSS patterns, mixins, BEM conventions
🎨 Design System Documentation (MANDATORY)
Before creating any component, read the design system documentation for your target application:
| Application | Design System Location |
|---|---|
| WebV2 Apps | docs/design-system/ |
| TextSnippetClient | src/PlatformExampleAppWeb/apps/playground-text-snippet/docs/design-system/ |
Key docs to read:
README.md- Component overview, base classes, library summary02-component-catalog.md- Available components and usage examples01-design-tokens.md- Colors, typography, spacing tokens07-technical-guide.md- Implementation checklist
Component Hierarchy
PlatformComponent # Base: lifecycle, subscriptions, signals
├── PlatformVmComponent # + ViewModel injection
├── PlatformFormComponent # + Reactive forms integration
└── PlatformVmStoreComponent # + ComponentStore state management
AppBaseComponent # + Auth, roles, company context
├── AppBaseVmComponent # + ViewModel + auth context
├── AppBaseFormComponent # + Forms + auth + validation
└── AppBaseVmStoreComponent # + Store + auth + loading/error
Component Type Decision
| Scenario | Base Class | Use When |
|---|---|---|
| Simple display | AppBaseComponent |
Static content, no state |
| With ViewModel | AppBaseVmComponent |
Needs mutable view model |
| Form with validation | AppBaseFormComponent |
User input forms |
| Complex state/CRUD | AppBaseVmStoreComponent |
Lists, dashboards, multi-step |
File Location
src/PlatformExampleAppWeb/apps/{app-name}/src/app/
└── features/{feature}/
├── {feature}.component.ts
├── {feature}.component.html
├── {feature}.component.scss
└── {feature}.store.ts (if using store)
Component HTML Template Standard (BEM Classes)
All UI elements in component templates MUST have BEM classes, even without styling needs. This makes HTML self-documenting like OOP class hierarchy.
<!-- ✅ CORRECT: All elements have BEM classes for structure clarity -->
<div class="feature-card">
<div class="feature-card__header">
<h3 class="feature-card__title">{{ feature.name }}</h3>
<span class="feature-card__badge">{{ feature.status }}</span>
</div>
<div class="feature-card__body">
<p class="feature-card__description">{{ feature.description }}</p>
</div>
<div class="feature-card__footer">
<button class="feature-card__btn --edit" (click)="onEdit.emit(feature)">Edit</button>
<button class="feature-card__btn --delete" (click)="onDelete.emit(feature)">Delete</button>
</div>
</div>
<!-- ❌ WRONG: Elements without classes - structure unclear -->
<div class="feature-card">
<div>
<h3>{{ feature.name }}</h3>
<span>{{ feature.status }}</span>
</div>
<div>
<p>{{ feature.description }}</p>
</div>
<div>
<button (click)="onEdit.emit(feature)">Edit</button>
<button (click)="onDelete.emit(feature)">Delete</button>
</div>
</div>
BEM Naming Convention:
- Block: Component name (e.g.,
feature-card) - Element: Child using
block__element(e.g.,feature-card__header) - Modifier: Separate class with
--prefix (e.g.,feature-card__btn --edit --small)
Component SCSS Standard
Always style both the host element (Angular selector) and the main wrapper class:
@import '~assets/scss/variables';
// Host element styling - ensures Angular element is a proper block container
my-component {
display: flex;
flex-direction: column;
}
// Main wrapper class with full styling
.my-component {
display: flex;
flex-direction: column;
width: 100%;
flex-grow: 1;
&__header {
// BEM child elements...
}
&__content {
flex: 1;
overflow-y: auto;
}
}
Why both?
- Host element: Makes the Angular element a real layout element (not an unknown element without display)
- Main class: Contains the full styling, matches the wrapper div in HTML
Pattern 1: List Component with Store
Store
@Injectable()
export class FeatureListStore extends PlatformVmStore<FeatureListState> {
protected override vmConstructor = (data?: Partial<FeatureListState>) => ({ items: [], filters: {}, ...data }) as FeatureListState;
public readonly items$ = this.select(state => state.items);
public loadItems = this.effectSimple(
() => this.featureApi.getList(this.currentVm().filters).pipe(this.tapResponse(items => this.updateState({ items }))),
'loadItems'
);
constructor(private featureApi: FeatureApiService) {
super();
}
}
Component
@Component({
selector: 'app-feature-list',
providers: [FeatureListStore]
})
export class FeatureListComponent extends AppBaseVmStoreComponent<FeatureListState, FeatureListStore> {
trackByItem = this.ngForTrackByItemProp<FeatureDto>('id');
constructor(store: FeatureListStore) {
super(store);
}
ngOnInit(): void {
this.store.loadItems();
}
}
Template
<app-loading-and-error-indicator [target]="this">
@if (vm(); as vm) { @for (item of vm.items; track trackByItem) {
<div>{{ item.name }}</div>
} @empty {
<div>No items found</div>
} }
</app-loading-and-error-indicator>
Pattern 2: Form Component
@Component({
selector: 'app-feature-form'
})
export class FeatureFormComponent extends AppBaseFormComponent<FeatureFormVm> {
protected initialFormConfig = () => ({
controls: {
name: new FormControl(this.currentVm().name, [Validators.required, noWhitespaceValidator]),
code: new FormControl(this.currentVm().code, [], [ifAsyncValidator(() => !this.isViewMode(), this.checkCodeUnique())])
},
dependentValidations: { code: ['status'] }
});
protected initOrReloadVm = (isReload: boolean) => {
return this.mode === 'create' ? of<FeatureFormVm>({ name: '', code: '' }) : this.featureApi.getById(this.featureId);
};
onSubmit(): void {
if (!this.validateForm()) return;
this.featureApi.save(this.currentVm()).pipe(this.observerLoadingErrorState('save'), this.untilDestroyed()).subscribe();
}
}
Key Platform APIs
// Auto-cleanup subscription
this.data$.pipe(this.untilDestroyed()).subscribe();
// Track request state
observable.pipe(this.observerLoadingErrorState('requestKey'));
// Check states
isLoading$('requestKey')();
getErrorMsg$('requestKey')();
// Track-by for @for loops
trackByItem = this.ngForTrackByItemProp<Item>('id');
Code Responsibility Hierarchy (CRITICAL)
Components should only handle UI events - delegate all logic to lower layers:
| Layer | Responsibility |
|---|---|
| Entity/Model | Display helpers, dropdown options, defaults, static factory methods |
| Service | API calls, command factories |
| Component | UI event handling ONLY |
// ❌ WRONG: Logic in component (causes duplication)
readonly statusOptions = [{ value: 1, label: 'Active' }, ...];
getStatusClass(item) { return item.isActive ? 'active' : 'inactive'; }
// ✅ CORRECT: Delegate to entity
readonly statusOptions = Entity.getStatusOptions();
getStatusClass(item) { return item.getStatusCssClass(); }
Anti-Patterns to AVOID
- Using wrong base class (PlatformComponent when auth needed)
- Manual subscription management without untilDestroyed()
- Direct HttpClient usage (use API services)
- Missing loading states (use app-loading-and-error-indicator)
- Putting reusable logic in component instead of entity/model
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?