Component Interaction Strategies in Angular
Explore various strategies for facilitating component interaction, from input and output decorators to services for shared state.
0 likes
42 views
Rule Content
{ "title": "Component Interaction Strategies in Angular", "description": "Explore various strategies for facilitating component interaction, from input and output decorators to services for shared state.", "category": "Angular Cursor Rules", "rules": [ { "name": "Use @Input and @Output Decorators for Parent-Child Communication", "description": "Facilitate data flow between parent and child components using @Input for data binding and @Output with EventEmitter for event handling.", "examples": [ { "code": "@Component({\n selector: 'app-child',\n template: '<button (click)=\"notifyParent()\">Click Me</button>'\n})\nexport class ChildComponent {\n @Output() notify = new EventEmitter<void>();\n\n notifyParent() {\n this.notify.emit();\n }\n}\n\n@Component({\n selector: 'app-parent',\n template: '<app-child (notify)=\"onNotify()\"></app-child>'\n})\nexport class ParentComponent {\n onNotify() {\n console.log('Child component event received');\n }\n}" } ] }, { "name": "Utilize Services for Shared State Management", "description": "Implement services to manage shared state and facilitate communication between sibling components or components at different levels in the component tree.", "examples": [ { "code": "@Injectable({ providedIn: 'root' })\nexport class SharedService {\n private dataSubject = new BehaviorSubject<string>('');\n data$ = this.dataSubject.asObservable();\n\n updateData(data: string) {\n this.dataSubject.next(data);\n }\n}\n\n@Component({\n selector: 'app-sibling1',\n template: '<input (input)=\"updateData($event.target.value)\" />'\n})\nexport class Sibling1Component {\n constructor(private sharedService: SharedService) {}\n\n updateData(value: string) {\n this.sharedService.updateData(value);\n }\n}\n\n@Component({\n selector: 'app-sibling2',\n template: '<p>{{ data }}</p>'\n})\nexport class Sibling2Component implements OnInit {\n data: string;\n\n constructor(private sharedService: SharedService) {}\n\n ngOnInit() {\n this.sharedService.data$.subscribe(data => this.data = data);\n }\n}" } ] }, { "name": "Implement Reactive Programming with RxJS for Component Communication", "description": "Leverage RxJS Observables to create reactive data streams for efficient and decoupled component communication.", "examples": [ { "code": "@Injectable({ providedIn: 'root' })\nexport class DataService {\n private dataSubject = new Subject<string>();\n data$ = this.dataSubject.asObservable();\n\n sendData(data: string) {\n this.dataSubject.next(data);\n }\n}\n\n@Component({\n selector: 'app-sender',\n template: '<button (click)=\"sendData()\">Send Data</button>'\n})\nexport class SenderComponent {\n constructor(private dataService: DataService) {}\n\n sendData() {\n this.dataService.sendData('Hello from Sender');\n }\n}\n\n@Component({\n selector: 'app-receiver',\n template: '<p>{{ receivedData }}</p>'\n})\nexport class ReceiverComponent implements OnInit {\n receivedData: string;\n\n constructor(private dataService: DataService) {}\n\n ngOnInit() {\n this.dataService.data$.subscribe(data => this.receivedData = data);\n }\n}" } ] }, { "name": "Avoid Nested Subscriptions in RxJS", "description": "Prevent memory leaks and improve code readability by avoiding nested subscriptions; use higher-order mapping operators like switchMap instead.", "examples": [ { "code": "import { switchMap } from 'rxjs/operators';\n\nthis.observable1.pipe(\n switchMap(data1 => this.observable2)\n).subscribe(data2 => {\n // Process data\n});" } ] }, { "name": "Use OnPush Change Detection Strategy for Performance Optimization", "description": "Enhance performance by setting the change detection strategy to OnPush, which reduces the number of change detection cycles.", "examples": [ { "code": "@Component({\n selector: 'app-optimized',\n templateUrl: './optimized.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class OptimizedComponent {\n // Component logic\n}" } ] }, { "name": "Implement Lazy Loading for Feature Modules", "description": "Improve application load time and performance by implementing lazy loading for feature modules.", "examples": [ { "code": "const routes: Routes = [\n { path: 'feature', loadChildren: () => import('./feature/feature.module').then(m => m.FeatureModule) }\n];" } ] }, { "name": "Use Angular's Signals for State Management", "description": "Leverage Angular's Signals system for efficient state management and reactive programming.", "examples": [ { "code": "import { signal } from '@angular/core';\n\nconst count = signal(0);\n\nfunction increment() {\n count.set(count() + 1);\n}" } ] }, { "name": "Utilize the inject Function for Service Injection", "description": "Use the inject function for injecting services directly within component, directive, or service logic, enhancing clarity and reducing boilerplate.", "examples": [ { "code": "import { inject } from '@angular/core';\n\nconst myService = inject(MyService);" } ] }, { "name": "Use the NgOptimizedImage Directive for Efficient Image Loading", "description": "Enhance image loading and performance by using the NgOptimizedImage directive, which provides built-in optimization features.", "examples": [ { "code": "<img ngSrc=\"image.jpg\" width=\"500\" height=\"300\" />" } ] }, { "name": "Implement Deferrable Views for Optimizing Component Rendering", "description": "Optimize rendering performance by deferring non-essential views until necessary, reducing initial load time.", "examples": [ { "code": "<ng-container *ngIf=\"isLoaded; else loading\">\n <!-- Content to display when loaded -->\n</ng-container>\n<ng-template #loading>\n <!-- Loading indicator -->\n</ng-template>" } ] } ] }