Utils

Rename Collection Schematic

A schematic for renaming collection-based properties in your ngrx store and related files. Useful for refactoring collection names or completing migrations the automatic migrator couldn't handle.

Usage

ng g @ngrx-traits/signals:rename-collection --old-name=<name> [--new-name=<name>] [--path=<path>]

Parameters

Parameter Required Default Description
--old-name Yes - Current collection name to find
--new-name No oldName New collection name (defaults to oldName for v21 migration)
--path No src Directory to search for files

Example: v21 Migration Fix

If the automatic migration missed some files, use this schematic:

# Adds 'Entities' suffix to 'product' collection properties
ng g @ngrx-traits/signals:rename-collection --old-name=product --path=src/app

This transforms:

// Before
store.productCallStatus();
store.isProductLoading();
store.loadProductPage(1);
store.productFilter();

// After
store.productEntitiesCallStatus();
store.isProductEntitiesLoading();
store.loadProductEntitiesPage({ pageIndex: 1 });
store.productEntitiesFilter();

Example: Rename Collection

Rename a collection from product to item:

ng g @ngrx-traits/signals:rename-collection --old-name=product --new-name=item --path=src/app

This transforms a complex store feature with filter, pagination, sort and loading:

// Before
const productEntityConfig = entityConfig({
  entity: type<Product>(),
  collection: 'product',
});

const productsStoreFeature = signalStoreFeature(
  withEntities(productEntityConfig),
  withCallStatus({
    ...productEntityConfig,
    initialValue: 'loading',
    errorType: type<string>(),
  }),
  withEntitiesRemoteFilter({
    ...productEntityConfig,
    defaultFilter: { search: '' },
  }),
  withEntitiesRemotePagination({
    ...productEntityConfig,
    pageSize: 10,
  }),
  withEntitiesRemoteSort({
    ...productEntityConfig,
    defaultSort: { field: 'name', direction: 'asc' },
  }),
  withEntitiesLoadingCall(
    ({ productEntitiesPagedRequest, productEntitiesFilter, productEntitiesSort }) => ({
      ...productEntityConfig,
      fetchEntities: async () => {
        const res = await lastValueFrom(
          inject(ProductService).getProducts({
            search: productEntitiesFilter().search,
            skip: productEntitiesPagedRequest().startIndex,
            take: productEntitiesPagedRequest().size,
            sortAscending: productEntitiesSort().direction === 'asc',
            sortColumn: productEntitiesSort().field,
          }),
        );
        return { entities: res.resultList, total: res.total };
      },
    }),
  ),
);

// Usages
store.productEntitiesFilter();
store.productEntitiesSort();
store.productEntitiesCurrentPage();
store.isProductEntitiesLoading();
store.loadProductEntitiesPage({ pageIndex: 1 });
// After
const productEntityConfig = entityConfig({
  entity: type<Product>(),
  collection: 'item',
});

const productsStoreFeature = signalStoreFeature(
  withEntities(productEntityConfig),
  withCallStatus({
    ...productEntityConfig,
    initialValue: 'loading',
    errorType: type<string>(),
  }),
  withEntitiesRemoteFilter({
    ...productEntityConfig,
    defaultFilter: { search: '' },
  }),
  withEntitiesRemotePagination({
    ...productEntityConfig,
    pageSize: 10,
  }),
  withEntitiesRemoteSort({
    ...productEntityConfig,
    defaultSort: { field: 'name', direction: 'asc' },
  }),
  withEntitiesLoadingCall(
    ({ itemEntitiesPagedRequest, itemEntitiesFilter, itemEntitiesSort }) => ({
      ...productEntityConfig,
      fetchEntities: async () => {
        const res = await lastValueFrom(
          inject(ProductService).getProducts({
            search: itemEntitiesFilter().search,
            skip: itemEntitiesPagedRequest().startIndex,
            take: itemEntitiesPagedRequest().size,
            sortAscending: itemEntitiesSort().direction === 'asc',
            sortColumn: itemEntitiesSort().field,
          }),
        );
        return { entities: res.resultList, total: res.total };
      },
    }),
  ),
);

// Usages
store.itemEntitiesFilter();
store.itemEntitiesSort();
store.itemEntitiesCurrentPage();
store.isItemEntitiesLoading();
store.loadItemEntitiesPage(1);

What Gets Renamed

The schematic renames all collection-based properties:

CallStatus Properties

  • {old}CallStatus{new}EntitiesCallStatus
  • {old}Error{new}EntitiesError
  • is{Old}Loadingis{New}EntitiesLoading
  • is{Old}Loadedis{New}EntitiesLoaded
  • set{Old}Loadingset{New}EntitiesLoading
  • set{Old}Loadedset{New}EntitiesLoaded
  • set{Old}Errorset{New}EntitiesError

Pagination Properties

  • {old}Pagination{new}EntitiesPagination
  • {old}CurrentPage{new}EntitiesCurrentPage
  • {old}PagedRequest{new}EntitiesPagedRequest
  • load{Old}Pageload{New}EntitiesPage
  • set{Old}PagedResultset{New}EntitiesPagedResult
  • loadMore{Old}loadMore{New}Entities
  • load{Old}NextPageload{New}EntitiesNextPage
  • load{Old}PreviousPageload{New}EntitiesPreviousPage
  • load{Old}FirstPageload{New}EntitiesFirstPage

Filter Properties

  • {old}Filter{new}EntitiesFilter
  • is{Old}FilterChangedis{New}EntitiesFilterChanged
  • reset{Old}Filterreset{New}EntitiesFilter
  • filter{Old}Entitiesfilter{New}Entities

Sort Properties

  • {old}Sort{new}EntitiesSort
  • sort{Old}sort{New}Entities

Selection Properties

  • {old}IdsSelectedMap{new}IdsSelectedMap
  • {old}EntitiesSelected{new}EntitiesSelected
  • {old}IdsSelected{new}IdsSelected
  • isAll{Old}SelectedisAll{New}EntitiesSelected
  • toggleSelectAll{Old}EntitiestoggleSelectAll{New}Entities
  • select{Old}Entitiesselect{New}Entities
  • deselect{Old}Entitiesdeselect{New}Entities
  • clear{Old}Selectionclear{New}EntitiesSelection

Entity Properties

  • {old}Entities{new}Entities
  • {old}Ids{new}Ids
  • {old}EntityMap{new}EntityMap

Collection Config

  • collection: '{old}'collection: '{new}'

File Types Processed

The schematic processes:

  • .ts files (TypeScript)
  • .html files (templates)

Files in node_modules and .git directories are automatically excluded.

Best Practices

  1. Commit before running: Always commit your changes before running the schematic
  2. Review changes: Check the git diff after running to verify the changes
  3. Run tests: Execute your test suite to catch any issues
  4. Multiple collections: Run the schematic once per collection you need to rename
# Rename multiple collections
ng g @ngrx-traits/signals:rename-collection --old-name=product
ng g @ngrx-traits/signals:rename-collection --old-name=order
ng g @ngrx-traits/signals:rename-collection --old-name=user