Lightweight
Lightweight

Reputation: 504

@ngrx/signals Store methods in separate file

I'm just starting to learn ngrx signals and one thing that struck me is that a "store" file could become quite large, quite quickly so ideally I would like to break it into separate parts.

Below is an example of how I might split out the "withMethods" factory but I cannot work out what the type of "store" should be in the bookMethodsFactory function and how I can avoid a circular dependency?

import { inject } from '@angular/core';
import { patchState, signalStore, withMethods, withState } from '@ngrx/signals';

// book.model.ts
export interface Book {
    id: number;
    title: string;
}

// books.service.ts
export class BooksService {
    public getBooks(): Promise<Book[]> {
        return Promise.resolve([
            { id: 1, title: 'Book 1' },
            { id: 2, title: 'Book 2' },
            { id: 3, title: 'Book 3' }
        ]);
    }
}

type BooksState = {
    books: Book[];
};

// book
const initialState: BooksState = {
    books: []
};

export const BooksStore = signalStore(
    { protectedState: false },
    withState(initialState),
    withMethods(bookMethodsFactory)
);

// book.methods.ts
export const bookMethodsFactory = ((store: ???) => {
    const bookService = inject(BooksService);

    return {
        async loadBooks(): Promise<void> {
            const books = await bookService.getBooks();
            patchState(store, { books });
        }
    }
});

Upvotes: 1

Views: 803

Answers (2)

Fateh Mohamed
Fateh Mohamed

Reputation: 21367

In NGRX signal store you can create an extension using signalStoreFeature. It can be used in your case if you have a long list of withMethods functions, or you can use it to share code between signals stores.

So in your case, you can create a separate file book.signalMethods.ts

import { signalStoreFeature, withMethods } from '@ngrx/signals';

export function withMySeparatedMethods() {
 return signalStoreFeature(
    withMethods((store, bookService = inject(BooksService)) => {
      //loadBooks
      // function2
      // function3
      return { loadBooks, function2, function3 };
    })
  )
}

then all what you need to do is to import it in your main signal store

export const BooksStore = signalStore(
 { protectedState: false },
 withState(initialState),
 withMySeparatedMethods() // HERE
);

Upvotes: 4

Corentin Clichy
Corentin Clichy

Reputation: 29

Jumping on that response. Let's say I want to to add a withComputed to the signalStoreFeature. I struggle with that since store is not typed. Is there any type for this to get all properties from BookStore, to use it on the signalStoreFeature?

 import { signalStoreFeature, withMethods } from '@ngrx/signals';
    
    export function withMySeparatedMethods() {
     return signalStoreFeature(
        withComputed((store) => ({

          // here store is not type how can I have the type of the global 
          store state

          baz: store.
        }),
        withMethods((store, bookService = inject(BooksService)) => {
          //loadBooks
          // function2
          // function3
          return { loadBooks, function2, function3 };
        })
      )
    }

Upvotes: 2

Related Questions