0

I have a simple Angular app with standalone components, where I am using NGRX Component Store. I am trying to set the state from ComponentA and subscribing to those changes in all the components. But, only the current component shows the changes, not the remaining components. In the below code, I have a Service, Store and 2 components. When I try to setState from Home component, the About Component doesn't update with the respective changes.

Service:

import { HttpClient } from "@angular/common/http";
import { inject, Injectable } from "@angular/core";
import { delay, Observable, of } from "rxjs";

const task = [
  {name: "test1", id:"a1"},
  {name: "test2", id:"a2"},
]

@Injectable()
export class Service {
  public get(): Observable<any> {
    return of(task).pipe(delay(1000));
  }
}

Store.ts

import { Injectable } from '@angular/core';
import { ComponentStore } from '@ngrx/component-store';
import { EMPTY, Observable } from 'rxjs';
import { catchError, switchMap, tap } from 'rxjs/operators';
import { Service } from './app.service';

export interface Task {
  name: string;
  id: string;
}
export interface TaskState {
  task: Task[];
  searchString: string;
}

@Injectable()
export class TaskStore extends ComponentStore<TaskState> {
  constructor(private taskService: Service) {
    super({
      task: [],
      searchString: '',
    });

    this.fetchTask();
  }

  readonly setTask = this.updater((state, task: Task[]) => ({
    ...state,
    task,
  }));

  public readonly setCurrentTask = this.updater((state, currentTask: Task) => ({
    ...state,
    currentTask,
  }));


  readonly filteredTasks$: Observable<Task[]> = this.select(
    ({ task, searchString }) =>
      task.filter((c) =>
        c.name.toLowerCase().includes(searchString.toLowerCase())
      )
  );

  readonly fetchTask = this.effect((trigger$) =>
    trigger$.pipe(
      switchMap(() =>
        this.taskService.get().pipe(
          tap((task: Task[]) => {
            this.setTask(task);
          }),
          catchError(() => EMPTY)
        )
      )
    )
  );
}

Home.component

import { AsyncPipe, NgFor } from '@angular/common';
import { Component, inject, OnInit } from '@angular/core';
import { provideComponentStore } from '@ngrx/component-store';
import { TaskStore } from '../store';

@Component({
  standalone: true,
  imports: [NgFor, AsyncPipe],
  selector: 'home',
  templateUrl: './home.component.html',
  providers: [provideComponentStore(TaskStore)],
})
export class HomeComponent implements OnInit {
  private store = inject(TaskStore);
  public tasks$ = this.store.filteredTasks$;
  ngOnInit() {
    this.store.filteredTasks$.subscribe((vm) => console.log(vm));
  }

  push() {
    this.store.setCurrentTask({
      name: 'test3',
      id: 'a3',
    });

    this.store.setTask([
      {
        name: 'test4',
        id: 'a4',
      },
    ]);
  }
}
<p>Home works!!</p>

<div *ngFor="let task of tasks$ | async">
  <p>{{task.name }}</p>
</div>

<button (click) = "push()">Push data</button>

About.component

import { AsyncPipe, NgFor } from '@angular/common';
import { Component, inject, OnInit } from '@angular/core';
import { provideComponentStore } from '@ngrx/component-store';
import { TaskStore } from '../store';

@Component({
  standalone: true,
  imports: [NgFor, AsyncPipe],
  selector: 'about',
  templateUrl: './about.component.html',
  providers: [provideComponentStore(TaskStore)],
})
export class AboutComponent implements OnInit {
  private store = inject(TaskStore);
  public tasks$ = this.store.filteredTasks$;
  ngOnInit() {
    this.store.filteredTasks$.subscribe((vm) => console.log('vm', vm));
  }
}
---------------------------------
<p>About works</p>

<div *ngFor="let task of tasks$ | async">
  <p>{{task.name }}</p>
</div>

When I click on the button to setState of the tasks, the home component updates but not the About. What Am I doing wrong here?

Here is a Stackblitz: https://stackblitz.com/edit/angular-pi1j19?file=src%2Fapp%2Fabout%2Fabout.component.html

tangel
  • 309
  • 1
  • 3
  • 12

0 Answers0