Component Patterns
Component Class Suffix
All components must use theComponent suffix (@angular-eslint/component-class-suffix):
Directive Class Suffix
All directives must use theDirective suffix (@angular-eslint/directive-class-suffix):
Change Detection Strategy
Prefer OnPush change detection for better performance (@angular-eslint/prefer-on-push-component-change-detection):
- Improved performance by reducing change detection cycles
- Forces better data flow patterns
- Explicit state management
Lifecycle Hooks
Implement Lifecycle Interfaces
Always implement the corresponding interface (@angular-eslint/use-lifecycle-interface):
Contextual Lifecycle
Use lifecycle hooks appropriately for their context (@angular-eslint/contextual-lifecycle):
- Don’t use component hooks in directives
- Don’t use directive hooks in components
- Use the right hook for the right job
Input/Output Patterns
No Input/Output Metadata
Don’t useinputs and outputs metadata arrays (@angular-eslint/no-inputs-metadata-property, @angular-eslint/no-outputs-metadata-property):
No Output Rename
Don’t rename outputs (@angular-eslint/no-output-rename):
Prefer Signals
Use Angular signals for reactive state (@angular-eslint/prefer-signals):
EventEmitter Type
UseEventEmitter with proper typing (@angular-eslint/prefer-output-emitter-ref):
Dependency Injection
Constructor Injection
Use constructor injection for services:Modern inject() Function
While@angular-eslint/prefer-inject is currently disabled, the inject() function is available:
RxJS Best Practices
Automatic Unsubscription
UsetakeUntilDestroyed to automatically unsubscribe (rxjs-angular/prefer-takeuntil):
Subject Protection
Don’t expose rawSubject instances - only expose as Observable (rxjs/no-exposed-subjects):
RxJS Recommended Rules
All rules fromeslint-plugin-rxjs recommended config are enabled, including:
- No nested subscriptions
- No subscribe in subscribe
- Proper error handling
- Unsubscribe from finite observables
Template Patterns
Button Type Attribute
All buttons must have an explicittype attribute (@angular-eslint/template/button-has-type):
Inline Templates
Inline templates are processed automatically by ESLint (angular.processInlineTemplates):
Custom Bitwarden Rules
Required Labels on Icons
Icon buttons require accessibility labels (@bitwarden/components/require-label-on-biticonbutton):
No BWI Class Usage
Avoid usingbwi-* classes directly in templates (@bitwarden/components/no-bwi-class-usage):
No Icon Children in Buttons
Don’t nest icons inside bit-button components (@bitwarden/components/no-icon-children-in-bit-button):
Pipes
Implement PipeTransform
All pipes must implement thePipeTransform interface (currently disabled):
Standalone Components
While@angular-eslint/prefer-standalone is currently disabled, standalone components are the modern approach:
Admin Console Strict Rules
Thelibs/admin-console and admin-console app directories enforce stricter Angular rules:
@angular-eslint/no-empty-lifecycle-method: "error"@angular-eslint/no-input-rename: "error"@angular-eslint/no-output-native: "error"@angular-eslint/no-output-on-prefix: "error"@angular-eslint/use-pipe-transform-interface: "error"
eslint.config.mjs:609-631 for the full configuration.
Next Steps
- Review TypeScript Style Guide for TypeScript patterns
- See Linting for complete ESLint rules
- Check Tailwind CSS for styling patterns