Angular Core Knowledge
Full Reference: See advanced.md for WebSocket service with signals, RxJS WebSocketSubject, Socket.IO integration, and room management patterns.
Deep Knowledge: Use mcp__documentation__fetch_docs with technology: angular for comprehensive documentation.
When NOT to Use This Skill
Skip this skill when:
-
Working with AngularJS (1.x) - legacy framework
-
Building React applications (use frontend-react )
-
Using Vue framework (use vue-composition )
-
Working with Svelte (use svelte )
-
Need only TypeScript without framework (use typescript )
Standalone Components (Angular 17+)
import { Component, signal, computed } from '@angular/core'; import { CommonModule } from '@angular/common';
@Component({
selector: 'app-counter',
standalone: true,
imports: [CommonModule],
template: <button (click)="increment()"> Count: {{ count() }} </button> <p>Double: {{ double() }}</p>
})
export class CounterComponent {
count = signal(0);
double = computed(() => this.count() * 2);
increment() { this.count.update(n => n + 1); } }
Signals (Angular 16+)
API Purpose
signal()
Create reactive value
computed()
Derived signal
effect()
Side effects
input()
Signal-based input
output()
Signal-based output
Dependency Injection
@Injectable({ providedIn: 'root' }) export class UserService { private http = inject(HttpClient);
getUsers() { return this.http.get<User[]>('/api/users'); } }
Key Patterns
-
Prefer standalone components
-
Use signals over RxJS for simple state
-
inject() function over constructor injection
-
Lazy load routes for performance
Anti-Patterns
Anti-Pattern Why It's Bad Correct Approach
Using NgModules for new apps Outdated, verbose Use standalone components
Constructor injection only Less flexible Use inject() function
Not using OnPush change detection Poor performance Use OnPush + signals
Subscribing without unsubscribe Memory leaks Use async pipe or takeUntilDestroyed()
Inline styles with CSP Security issues Use external stylesheets
Not lazy loading routes Large bundle size Lazy load feature modules
Quick Troubleshooting
Issue Likely Cause Solution
Expression changed after check Modifying state during CD Use ChangeDetectorRef.detectChanges()
Service not found Wrong providedIn scope Check @Injectable({ providedIn: 'root' })
Route not loading Missing lazy load syntax Use loadChildren: () => import()
Signal not updating view Not using signal setter Use .set() or .update()
Form not reactive Using template-driven forms Use ReactiveFormsModule
HTTP call not firing Forgot to subscribe Subscribe to Observable
Production Readiness
Security
// HTTP Interceptor for auth
export const authInterceptor: HttpInterceptorFn = (req, next) => {
const token = inject(AuthService).getToken();
if (token) {
req = req.clone({
setHeaders: { Authorization: Bearer ${token} }
});
}
return next(req);
};
Error Handling
// Global error handler @Injectable() export class GlobalErrorHandler implements ErrorHandler { private errorService = inject(ErrorTrackingService);
handleError(error: Error): void { console.error('Unhandled error:', error); this.errorService.trackError(error); } }
// Provide in app.config.ts export const appConfig: ApplicationConfig = { providers: [ { provide: ErrorHandler, useClass: GlobalErrorHandler }, ] };
Performance
// Lazy loading routes export const routes: Routes = [ { path: 'admin', loadChildren: () => import('./admin/routes').then(m => m.ADMIN_ROUTES), canActivate: [authGuard], }, ];
// Change detection optimization @Component({ changeDetection: ChangeDetectionStrategy.OnPush, ... }) export class OptimizedComponent { data = signal<Data | null>(null); }
// Defer loading
@Component({
template: @defer (on viewport) { <heavy-component /> } @placeholder { <skeleton-loader /> }
})
export class DeferredComponent {}
Testing
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { provideHttpClientTesting } from '@angular/common/http/testing';
describe('UserComponent', () => { let component: UserComponent; let fixture: ComponentFixture<UserComponent>;
beforeEach(async () => { await TestBed.configureTestingModule({ imports: [UserComponent], providers: [provideHttpClientTesting()] }).compileComponents();
fixture = TestBed.createComponent(UserComponent);
component = fixture.componentInstance;
});
it('should update signal', () => { component.count.set(5); expect(component.count()).toBe(5); expect(component.double()).toBe(10); }); });
Monitoring Metrics
Metric Target
First Contentful Paint < 1.5s
Largest Contentful Paint < 2.5s
Bundle size (initial) < 200KB
Time to Interactive < 3s
Checklist
-
Standalone components (Angular 17+)
-
Signals for reactive state
-
OnPush change detection
-
Lazy loaded routes
-
@defer for heavy components
-
Virtual scrolling for lists
-
Global error handler
-
HTTP interceptors for auth
-
SSR with Angular Universal
-
Zone-less for max performance
Reference Documentation
Deep Knowledge: Use mcp__documentation__fetch_docs with technology: angular for comprehensive documentation.
-
Signals Cheatsheet
-
Component Patterns