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>"
        }
      ]
    }
  ]
}