Search code examples
angularstate-managementangular-material-tableangular-signalsangular-state-managmement

Use one angular signal store for multiple features (components)


I've defined angular signal store in parent table component and update data using

patchState
export const TableStore = signalStore(
  { providedIn: 'root' },
  withRouteParams({ id: param => Number(param) }),
  withState(tableInitialState),
  withMethods((store, tableApiService = inject(TableApiService)) => ({
    getRows: rxMethod<number>(
      pipe(
        switchMap(structureId => {
          patchState(store, { loading: true });
          return tableApiService.getData(id).pipe(
            tap({
              next: (data: any) =>
                patchState(store, {
                  rows: data.rows,
                }),
              error: () =>
                patchState(store, {
                  rows: tableInitialState.rows,
                  loading: false,
                }),
              finalize: () => patchState(store, { loading: false }),
            })
          );
        })
      )
    ),
    addRow: rxMethod<Row>(...)
    ),
  })),

Code above works as expected and rows can be accessed via

store.rows()

Within the table there is an edit action which opens dialog component for the clicked row. In the dialog component I'm trying to get those rows from the same signal store;

export class DialogComponent {
   tableStore = inject(TableStore);

   ngOnInit() {
     console.log(this.tableStore.rows()); <== EMPTY ARRAY??
   }
}

but there are no data.

Does anyone know why? I've imagined table signal store to be domain level store and it's state could be used by several features at the same domain.

I've tried to get data from the table store in dialog component and create another dialog store in order to inject table store and get data from there but rows are empty as well.

export const DialogStore = signalStore(
  withMethods(
    (
      dialogStore,
      tableStore = inject(TableStore),
      tableApiService = inject(TableApiService)
    ) => ({
     updateRow: rxMethod<Row>(
        pipe(
          switchMap(updatedRow => {
            patchState(tableStore, { loading: true });
            return tableApiService
              .updateRow(updatedRow.id, updatedRow )
              .pipe(
                tapResponse({
                  next: () => {
                    console.log(tableStore.rows()), <= EMPTY ARRAY
                      patchState(tableStore, {
                        rows: tableStore
                          .rows()
                          .map(row =>
                            row.rowId === updatedRow.rowId
                              ? { ...row }
                              : row
                          ),
                      });
                    console.log(tableStore.rows()); <= EMPTY ARRAY
                  },
              );
          })
        )
      ),
})

Solution

  • It seems you have stated your TableStore in one's or multiple's component providers: [] section. Because of this there are multiple independent instances of TableStore across the application.

    considering that you are using { providedIn: 'root' }, you can just remove it from all of providers arrays and it should then work