ng-simple-state
TypeScript icon, indicating that this package has built-in type declarations

17.0.4 • Public • Published

NgSimpleState Build Status Coverage Status NPM version Maintainability

Simple state management in Angular with only Services and RxJS or Signal.

Description

Sharing state between components as simple as possible and leverage the good parts of component state and Angular's dependency injection system.

See the demos:

Get Started

Step 1: install ng-simple-state

npm i ng-simple-state

Step 2: Import NgSimpleStateModule into your AppModule

NgSimpleStateModule has some global optional config defined by NgSimpleStateConfig interface:

Option Description Default
enableDevTool if true enable Redux DevTools browser extension for inspect the state of the store. false
enableLocalStorage if true latest state of store is saved in local storage and reloaded on store initialization. false
persistentStorage Set the persistent storage local or session. local
comparator A function used to compare the previous and current state for equality. a === b

Side note: each store can be override the global configuration implementing storeConfig() method (see "Override global config").

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { CommonModule } from '@angular/common';
import { NgSimpleStateModule } from 'ng-simple-state';
import { environment } from '../environments/environment';

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    CommonModule,
    NgSimpleStateModule.forRoot({
      enableDevTool: !environment.production, // Enable Redux DevTools only in development mode
      enableLocalStorage: false // Local storage state persistence is globally disabled
    }) 
  ],
  bootstrap: [AppComponent],
})
export class AppModule {}

Step 3: Chose your store

There are two type of store NgSimpleStateBaseRxjsStore based on RxJS BehaviorSubject and NgSimpleStateBaseSignalStore based on Angular Signal:

RxJS Store

This is an example for a counter store in a src/app/counter-store.ts file. Obviously, you can create every store you want with every complexity you need.

  1. Define your state interface, eg.:
export interface CounterState {
    count: number;
}
  1. Define your store service by extending NgSimpleStateBaseRxjsStore, eg.:
import { Injectable } from '@angular/core';
import { NgSimpleStateBaseRxjsStore } from 'ng-simple-state';

export interface CounterState {
    count: number;
}
 
@Injectable()
export class CounterStore extends NgSimpleStateBaseRxjsStore<CounterState> {
 
}
  1. Implement initialState() and storeConfig() methods and provide the initial state of the store, eg.:
import { Injectable } from '@angular/core';
import { NgSimpleStateBaseRxjsStore, NgSimpleStateStoreConfig } from 'ng-simple-state';

export interface CounterState {
    count: number;
}
 
@Injectable()
export class CounterStore extends NgSimpleStateBaseRxjsStore<CounterState> {

  storeConfig(): NgSimpleStateStoreConfig {
    return {
      storeName: 'CounterStore'
    };
  }
  
  initialState(): CounterState {
    return {
      count: 0
    };
  }

}
  1. Implement one or more selectors of the partial state you want, in this example selectCount() eg.:
import { Injectable } from '@angular/core';
import { NgSimpleStateBaseRxjsStore, NgSimpleStateStoreConfig } from 'ng-simple-state';
import { Observable } from 'rxjs';

export interface CounterState {
    count: number;
}
 
@Injectable()
export class CounterStore extends NgSimpleStateBaseRxjsStore<CounterState> {

  storeConfig(): NgSimpleStateStoreConfig {
    return {
      storeName: 'CounterStore'
    };
  }
  
  initialState(): CounterState {
    return {
      count: 0
    };
  }

  selectCount(): Observable<number> {
    return this.selectState(state => state.count);
  }
}
  1. Implement one or more actions for change the store state, in this example increment() and decrement() eg.:
import { Injectable } from '@angular/core';
import { NgSimpleStateBaseRxjsStore, NgSimpleStateStoreConfig } from 'ng-simple-state';
import { Observable } from 'rxjs';

export interface CounterState {
  count: number;
}

@Injectable()
export class CounterStore extends NgSimpleStateBaseRxjsStore<CounterState> {

  storeConfig(): NgSimpleStateStoreConfig {
    return {
      storeName: 'CounterStore'
    };
  }

  initialState(): CounterState {
    return {
      count: 0
    };
  }

  selectCount(): Observable<number> {
    return this.selectState(state => state.count);
  }

  increment(increment: number = 1): void {
    this.setState(state => ({ count: state.count + increment }));
  }

  decrement(decrement: number = 1): void {
    this.setState(state => ({ count: state.count - decrement }));
  }
}

Step 3: Inject your store into the providers of the module you want (or the providers of component), eg.:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { CommonModule } from '@angular/common';
import { NgSimpleStateModule } from 'ng-simple-state';
import { environment } from '../environments/environment';
import { CounterStore } from './counter-store';

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    CommonModule,
    NgSimpleStateModule.forRoot({
      enableDevTool: !environment.production, // Enable Redux DevTools only in developing
      enableLocalStorage: false // Local storage state persistence is globally disabled
    })
  ],
  bootstrap: [AppComponent],
  providers: [CounterStore]  // The CounterStore state is shared at AppModule level
})
export class AppModule {}

Step 4: Use your store into the components, eg.:

import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { CounterStore } from './counter-store';

@Component({
  selector: 'app-root',
  template: `
  <h1>Counter: {{ counter$ | async }}</h1>
  <button (click)="counterStore.decrement()">Decrement</button>
  <button (click)="counterStore.resetState()">Reset</button>
  <button (click)="counterStore.increment()">Increment</button>
  `,
})
export class AppComponent {
  public counter$: Observable<number>;

  constructor(public counterStore: CounterStore) {
    this.counter$ = this.counterStore.selectCount();
  }
}

That's all!

alt text

Manage component state without service

If you want manage just a component state without make a new service, your component can extend directly NgSimpleStateBaseRxjsStore:

import { Component, Injector } from '@angular/core';
import { CommonModule } from '@angular/common';
import { NgSimpleStateBaseRxjsStore } from 'ng-simple-state';
import { Observable } from 'rxjs';

export interface CounterState {
    count: number;
}

@Component({
    selector: 'ng-counter',
    template: `
        {{counter$ | async}}
        <button (click)="increment()">+</button>
        <button (click)="decrement()">-</button>
    `
})
export class CounterComponent extends NgSimpleStateBaseRxjsStore<CounterState> {

    public counter$: Observable<number> = this.selectState(state => state.count);

    constructor(injector: Injector) {
      super(injector);
    }

    storeConfig(): NgSimpleStateStoreConfig {
      return {
        storeName: 'CounterComponent'
      };
    }

    initialState(): CounterState {
        return {
            count: 0
        };
    }

    increment(): void {
        this.setState(state => ({ count: state.count + 1 }));
    }

    decrement(): void {
        this.setState(state => ({ count: state.count - 1 }));
    }
}

Store's dependency injection

If you need to inject something into your store (eg. HttpClient), you need to also inject the Angular Injector service to the super, eg.:

import { Injectable, Injector } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { NgSimpleStateBaseRxjsStore } from 'ng-simple-state';

@Injectable()
export class CounterStore extends NgSimpleStateBaseRxjsStore<CounterState> {

  constructor(injector: Injector, private http: HttpClient) {
    super(injector);
  }

  increment(increment: number = 1): void {
    this.http.post<CounterState>('https://localhost:300/api/increment', { increment }).subscribe(response => {
      // setState() from default use parent function name as action name for Redux DevTools.
      // In this case we provide a second parameter `actionName` because the parent function is anonymous function
      this.setState(() => ({ count: response.count }), 'increment');
    });
  }

}

Override global config

If you need to override the global module configuration provided by NgSimpleStateModule.forRoot() you can implement storeConfig() and return a specific configuration for the single store, eg.:

import { Injectable } from '@angular/core';
import { NgSimpleStateStoreConfig } from 'ng-simple-state';


@Injectable()
export class CounterStore extends NgSimpleStateBaseRxjsStore<CounterState> {

  override storeConfig(): NgSimpleStateStoreConfig {
    return {
      enableLocalStorage: true, // enable local storage for this store
      persistentStorage: 'session', // persistentStorage can be 'session' or 'local' (default is localStorage)
      storeName: 'CounterStore2', // For default the store name is the class name, you can set a specific name for this store (must be be unique)
    }
  }
}

The options are defined by NgSimpleStateStoreConfig interface:

Option Description Default
enableDevTool if true enable Redux DevTools browser extension for inspect the state of the store. false
enableLocalStorage if true latest state of store is saved in local storage and reloaded on store initialization. false
storeName The name used into Redux DevTools and local storage key. Class name
persistentStorage Set the persistent storage local or session local
comparator A function used to compare the previous and current state for equality. a === b

Testing

ng-simple-state is simple to test. Eg.:

import { TestBed } from '@angular/core/testing';
import { NgSimpleStateModule } from 'ng-simple-state';
import { CounterStore } from './counter-store';

describe('CounterStore', () => {

  let counterStore: CounterStore;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [
        NgSimpleStateModule.forRoot({
          enableDevTool: false,
          enableLocalStorage: false
        })
      ]
    });

    counterStore = new CounterStore(TestBed);
  });

  it('initialState', () => {
    expect(counterStore.getCurrentState()).toEqual({ count: 0 });
  });

  it('increment', () => {
    counterStore.increment();
    expect(counterStore.getCurrentState()).toEqual({ count: 1 });
  });

  it('decrement', () => {
    counterStore.decrement();
    expect(counterStore.getCurrentState()).toEqual({ count: -1 });
  });

  it('selectCount', (done) => {
    counterStore.selectCount().subscribe(value => {
      expect(value).toBe(0);
      done();
    });
  });

});

Example: array store

This is an example for a todo list store in a src/app/todo-store.ts file.

import { Injectable } from '@angular/core';
import { NgSimpleStateBaseRxjsStore } from 'ng-simple-state';
import { Observable } from 'rxjs';

export interface Todo {
  id: number;
  name: string;
  completed: boolean;
}

export type TodoState = Array<Todo>;

@Injectable()
export class TodoStore extends NgSimpleStateBaseRxjsStore<TodoState> {

  storeConfig(): NgSimpleStateStoreConfig {
    return {
      storeName: 'TodoStore'
    };
  }

  initialState(): TodoState {
    return [];
  }

  add(todo: Omit<Todo, 'id'>): void {
    this.setState(state =>  [...state, {...todo, id: Date.now()}]);
  }

  delete(id: number): void {
    this.setState(state => state.filter(item => item.id !== id) );
  }

  setComplete(id: number, completed: boolean = true): void {
    this.setState(state => state.map(item => item.id === id ? {...item, completed} : item) );
  }
}

usage:

import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { Todo, TodoStore } from './todo-store';

@Component({
  selector: 'app-root',
  template: `
    <input #newTodo> <button (click)="todoStore.add({name: newTodo.value, completed: false})">Add todo</button>
    <ol>
        <li *ngFor="let todo of todoList$ | async">
            <ng-container *ngIf="todo.completed">✅</ng-container> 
            {{ todo.name }} 
            <button (click)="todoStore.setComplete(todo.id, !todo.completed)">Mark as {{ todo.completed ? 'Not completed' : 'Completed' }}</button> 
            <button (click)="todoStore.delete(todo.id)">Delete</button>
        </li>
    </ol>
  `,
  providers: [TodoStore]
})
export class AppComponent {
  public todoList$: Observable<Todo[]>;

  constructor(public todoStore: TodoStore) {
    this.todoList$ = this.todoStore.selectState();
  }
}

NgSimpleStateBaseRxjsStore API

@Injectable()
@Directive()
export abstract class NgSimpleStateBaseRxjsStore<S extends object | Array<any>> implements OnDestroy {

    /**
     * Return the observable of the state
     * @returns Observable of the state
     */
    public get state(): BehaviorSubject<S>;

    constructor(@Inject(Injector) injector: Injector);

    /**
     * When you override this method, you have to call the `super.ngOnDestroy()` method in your `ngOnDestroy()` method.
     */
    ngOnDestroy(): void;

    /**
     * Reset store to first loaded store state:
     *  - the last saved state, if `enableLocalStorage` config is `true`
     *  - otherwise the initial state provided from `initialState()` method.
     */
    resetState(): boolean;

    /**
     * Restart the store to initial state provided from `initialState()` method
     */
    restartState(): boolean;

    /**
     * Override this method for set a specific config for the store
     * @returns NgSimpleStateStoreConfig
     */
    storeConfig(): NgSimpleStateStoreConfig;

    /**
     * Set into the store the initial state
     * @param injector current Injector
     * @returns The state object
     */
    initialState(injector?: Injector): S;

    /**
     * Select a store state
     * @param selectFn State selector (if not provided return full state)
     * @param comparator A function used to compare the previous and current state for equality. Defaults to a `===` check.
     * @returns Observable of the selected state
     */
    selectState<K>(selectFn?: (state: Readonly<S>) => K, comparator?: (previous: K, current: K) => boolean): Observable<K>;

    /**
     * Return the current store state (snapshot)
     * @returns The current state
     */
    getCurrentState(): Readonly<S>;

    /**
     * Return the first loaded store state:
     * the last saved state, if `enableLocalStorage` config is `true`;
     * otherwise the initial state provided from `initialState()` method.
     * @returns The first state
     */
    getFirstState(): Readonly<S> | null;

    /**
     * Set a new state
     * @param selectFn State reducer
     * @param actionName The action label into Redux DevTools (default is parent function name)
     * @returns True if the state is changed
     */
    setState(stateFn: (currentState: Readonly<S>) => Partial<S>, actionName?: string): boolean; 
}

Signal Store

This is an example for a counter store in a src/app/counter-store.ts file. Obviously, you can create every store you want with every complexity you need.

  1. Define your state interface, eg.:
export interface CounterState {
    count: number;
}
  1. Define your store service by extending NgSimpleStateBaseSignalStore, eg.:
import { Injectable } from '@angular/core';
import { NgSimpleStateBaseSignalStore } from 'ng-simple-state';

export interface CounterState {
    count: number;
}
 
@Injectable()
export class CounterStore extends NgSimpleStateBaseSignalStore<CounterState> {
 
}
  1. Implement initialState() and storeConfig() methods and provide the initial state of the store, eg.:
import { Injectable } from '@angular/core';
import { NgSimpleStateBaseSignalStore, NgSimpleStateStoreConfig } from 'ng-simple-state';

export interface CounterState {
    count: number;
}
 
@Injectable()
export class CounterStore extends NgSimpleStateBaseSignalStore<CounterState> {

  storeConfig(): NgSimpleStateStoreConfig {
    return {
      storeName: 'CounterStore'
    };
  }
  
  initialState(): CounterState {
    return {
      count: 0
    };
  }

}
  1. Implement one or more selectors of the partial state you want, in this example selectCount() eg.:
import { Injectable, Signal } from '@angular/core';
import { NgSimpleStateBaseSignalStore, NgSimpleStateStoreConfig } from 'ng-simple-state';

export interface CounterState {
    count: number;
}
 
@Injectable()
export class CounterStore extends NgSimpleStateBaseSignalStore<CounterState> {

  storeConfig(): NgSimpleStateStoreConfig {
    return {
      storeName: 'CounterStore'
    };
  }
  
  initialState(): CounterState {
    return {
      count: 0
    };
  }

  selectCount(): Signal<number> {
    return this.selectState(state => state.count);
  }
}
  1. Implement one or more actions for change the store state, in this example increment() and decrement() eg.:
import { Injectable, Signal } from '@angular/core';
import { NgSimpleStateBaseSignalStore, NgSimpleStateStoreConfig } from 'ng-simple-state';

export interface CounterState {
  count: number;
}

@Injectable()
export class CounterStore extends NgSimpleStateBaseSignalStore<CounterState> {

  storeConfig(): NgSimpleStateStoreConfig {
    return {
      storeName: 'CounterStore'
    };
  }

  initialState(): CounterState {
    return {
      count: 0
    };
  }

  selectCount(): Signal<number> {
    return this.selectState(state => state.count);
  }

  increment(increment: number = 1): void {
    this.setState(state => ({ count: state.count + increment }));
  }

  decrement(decrement: number = 1): void {
    this.setState(state => ({ count: state.count - decrement }));
  }
}

Step 3: Inject your store into the providers of the module you want (or the providers of component), eg.:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { CommonModule } from '@angular/common';
import { NgSimpleStateModule } from 'ng-simple-state';
import { environment } from '../environments/environment';
import { CounterStore } from './counter-store';

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    CommonModule,
    NgSimpleStateModule.forRoot({
      enableDevTool: !environment.production, // Enable Redux DevTools only in developing
      enableLocalStorage: false // Local storage state persistence is globally disabled
    })
  ],
  bootstrap: [AppComponent],
  providers: [CounterStore]  // The CounterStore state is shared at AppModule level
})
export class AppModule {}

Step 4: Use your store into the components, eg.:

import { Component, Signal } from '@angular/core';
import { CounterStore } from './counter-store';

@Component({
  selector: 'app-root',
  template: `
  <h1>Counter: {{ counterSig() }}</h1>
  <button (click)="counterStore.decrement()">Decrement</button>
  <button (click)="counterStore.resetState()">Reset</button>
  <button (click)="counterStore.increment()">Increment</button>
  `,
})
export class AppComponent {
  public counterSig: Signal<number>;

  constructor(public counterStore: CounterStore) {
    this.counterSig = this.counterStore.selectCount();
  }
}

That's all!

alt text

Manage component state without service

If you want manage just a component state without make a new service, your component can extend directly NgSimpleStateBaseSignalStore:

import { Component, Injector, Signal } from '@angular/core';
import { CommonModule } from '@angular/common';
import { NgSimpleStateBaseSignalStore } from 'ng-simple-state';

export interface CounterState {
    count: number;
}

@Component({
    selector: 'ng-counter',
    template: `
        {{counterSig()}}
        <button (click)="increment()">+</button>
        <button (click)="decrement()">-</button>
    `
})
export class CounterComponent extends NgSimpleStateBaseSignalStore<CounterState> {

    public counterSig: Signal<number> = this.selectState(state => state.count);

    constructor(injector: Injector) {
      super(injector);
    }

    storeConfig(): NgSimpleStateStoreConfig {
      return {
        storeName: 'CounterComponent'
      };
    }

    initialState(): CounterState {
        return {
            count: 0
        };
    }

    increment(): void {
        this.setState(state => ({ count: state.count + 1 }));
    }

    decrement(): void {
        this.setState(state => ({ count: state.count - 1 }));
    }
}

Store's dependency injection

If you need to inject something into your store (eg. HttpClient), you need to also inject the Angular Injector service to the super, eg.:

import { Injectable, Injector } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { NgSimpleStateBaseSignalStore } from 'ng-simple-state';

@Injectable()
export class CounterStore extends NgSimpleStateBaseSignalStore<CounterState> {

  constructor(injector: Injector, private http: HttpClient) {
    super(injector);
  }

  increment(increment: number = 1): void {
    this.http.post<CounterState>('https://localhost:300/api/increment', { increment }).subscribe(response => {
      // setState() from default use parent function name as action name for Redux DevTools.
      // In this case we provide a second parameter `actionName` because the parent function is anonymous function
      this.setState(() => ({ count: response.count }), 'increment');
    });
  }

}

Override global config

If you need to override the global module configuration provided by NgSimpleStateModule.forRoot() you can implement storeConfig() and return a specific configuration for the single store, eg.:

import { Injectable } from '@angular/core';
import { NgSimpleStateStoreConfig } from 'ng-simple-state';


@Injectable()
export class CounterStore extends NgSimpleStateBaseSignalStore<CounterState> {

  override storeConfig(): NgSimpleStateStoreConfig {
    return {
      enableLocalStorage: true, // enable local storage for this store
      persistentStorage: 'session', // persistentStorage can be 'session' or 'local' (default is localStorage)
      storeName: 'CounterStore2', // For default the store name is the class name, you can set a specific name for this store (must be be unique)
    }
  }
}

The options are defined by NgSimpleStateStoreConfig interface:

Option Description Default
enableDevTool if true enable Redux DevTools browser extension for inspect the state of the store. false
enableLocalStorage if true latest state of store is saved in local storage and reloaded on store initialization. false
storeName The name used into Redux DevTools and local storage key. Class name
persistentStorage Set the persistent storage local or session local
comparator A function used to compare the previous and current state for equality. a === b

Testing

ng-simple-state is simple to test. Eg.:

import { TestBed } from '@angular/core/testing';
import { NgSimpleStateModule } from 'ng-simple-state';
import { CounterStore } from './counter-store';

describe('CounterStore', () => {

  let counterStore: CounterStore;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [
        NgSimpleStateModule.forRoot({
          enableDevTool: false,
          enableLocalStorage: false
        })
      ]
    });

    counterStore = new CounterStore(TestBed);
  });

  it('initialState', () => {
    expect(counterStore.getCurrentState()).toEqual({ count: 0 });
  });

  it('increment', () => {
    counterStore.increment();
    expect(counterStore.getCurrentState()).toEqual({ count: 1 });
  });

  it('decrement', () => {
    counterStore.decrement();
    expect(counterStore.getCurrentState()).toEqual({ count: -1 });
  });

  it('selectCount', () => {
    const valueSig = counterStore.selectCount();
    expect(valueSig()).toBe(0);
  });

});

Example: array store

This is an example for a todo list store in a src/app/todo-store.ts file.

import { Injectable } from '@angular/core';
import { NgSimpleStateBaseSignalStore } from 'ng-simple-state';

export interface Todo {
  id: number;
  name: string;
  completed: boolean;
}

export type TodoState = Array<Todo>;

@Injectable()
export class TodoStore extends NgSimpleStateBaseSignalStore<TodoState> {

  storeConfig(): NgSimpleStateStoreConfig {
    return {
      storeName: 'TodoStore'
    };
  }

  initialState(): TodoState {
    return [];
  }

  add(todo: Omit<Todo, 'id'>): void {
    this.setState(state =>  [...state, {...todo, id: Date.now()}]);
  }

  delete(id: number): void {
    this.setState(state => state.filter(item => item.id !== id) );
  }

  setComplete(id: number, completed: boolean = true): void {
    this.setState(state => state.map(item => item.id === id ? {...item, completed} : item) );
  }
}

usage:

import { Component, Signal } from '@angular/core';
import { Todo, TodoStore } from './todo-store';

@Component({
  selector: 'app-root',
  template: `
    <input #newTodo> <button (click)="todoStore.add({name: newTodo.value, completed: false})">Add todo</button>
    <ol>
        <li *ngFor="let todo of todoListSig()">
            <ng-container *ngIf="todo.completed">✅</ng-container> 
            {{ todo.name }} 
            <button (click)="todoStore.setComplete(todo.id, !todo.completed)">Mark as {{ todo.completed ? 'Not completed' : 'Completed' }}</button> 
            <button (click)="todoStore.delete(todo.id)">Delete</button>
        </li>
    </ol>
  `,
  providers: [TodoStore]
})
export class AppComponent {
  public todoListSig: Signal<Todo[]>;

  constructor(public todoStore: TodoStore) {
    this.todoListSig = this.todoStore.selectState();
  }
}

NgSimpleStateBaseSignalStore API

@Injectable()
@Directive()
export abstract class NgSimpleStateBaseSignalStore<S extends object | Array<any>> implements OnDestroy {

    /**
     * Return the Signal of the state
     * @returns Signal of the state
     */
    public get state(): Signal<S>;

    constructor(@Inject(Injector) injector: Injector);

    /**
     * When you override this method, you have to call the `super.ngOnDestroy()` method in your `ngOnDestroy()` method.
     */
    ngOnDestroy(): void;

    /**
     * Reset store to first loaded store state:
     *  - the last saved state, if `enableLocalStorage` config is `true`
     *  - otherwise the initial state provided from `initialState()` method.
     */
    resetState(): boolean;

    /**
     * Restart the store to initial state provided from `initialState()` method
     */
    restartState(): boolean;

    /**
     * Override this method for set a specific config for the store
     * @returns NgSimpleStateStoreConfig
     */
    storeConfig(): NgSimpleStateStoreConfig;

    /**
     * Set into the store the initial state
     * @param injector current Injector
     * @returns The state object
     */
    initialState(injector?: Injector): S;

    /**
     * Select a store state
     * @param selectFn State selector (if not provided return full state)
     * @param comparator A function used to compare the previous and current state for equality. Defaults to a `===` check.
     * @returns Signal of the selected state
     */
    selectState<K>(selectFn?: (state: Readonly<S>) => K, comparator?: (previous: K, current: K) => boolean): Signal<K>;

    /**
     * Return the current store state (snapshot)
     * @returns The current state
     */
    getCurrentState(): Readonly<S>;

    /**
     * Return the first loaded store state:
     * the last saved state, if `enableLocalStorage` config is `true`;
     * otherwise the initial state provided from `initialState()` method.
     * @returns The first state
     */
    getFirstState(): Readonly<S> | null;

    /**
     * Set a new state
     * @param selectFn State reducer
     * @param actionName The action label into Redux DevTools (default is parent function name)
     * @returns True if the state is changed
     */
    setState(stateFn: (currentState: Readonly<S>) => Partial<S>, actionName?: string): boolean; 
}

Alternatives

Aren't you satisfied? there are some valid alternatives:

Support

This is an open-source project. Star this repository, if you like it, or even donate. Thank you so much!

My other libraries

I have published some other Angular libraries, take a look:

Package Sidebar

Install

npm i ng-simple-state

Weekly Downloads

60

Version

17.0.4

License

MIT

Unpacked Size

174 kB

Total Files

27

Last publish

Collaborators

  • nigro.simone