/observable-state

Custom written implementation for State Management in Angular

Primary LanguageTypeScriptMIT LicenseMIT

Observable state repo

This repository explains a custom implementation about Observable State explained in these articles (newest to oldest):

How to use observable state for ui components

import { InputState } from './input-state-decorator';
import { ObservableState } from './observable-state';
type MyUiComponentInputState = {
  firstName: string;
  lastNam: string;
  age: number;
}
type MyUiComponentState = MyUiComponentInputState & {
  showAge: number;
}
@Component({
  template: `
    <ng-container *ngIf="vm$|async as vm">
        <p>First Name: {{vm.firstName}}</p>
        <p>Last Name: {{vm.lastName}}</p>
        <p *ngIf="vm.showAge">Age: {{vm.age}}</p>
        <button (click)="toggle()">Toggle Age</button>
    </ng-container>
  `
})
export class MyUiComponent extends ObservableState<MyUiComponentState> {
  @InputState() public readonly inputState$!: Observable<MyUiComponentInputState>
  @Input() public firstName = '';
  @Input() public lastName = '';
  @Input() public age = 0;
    
  constructor() {
    super();
    this.initialize({
      firstName: 'Brecht',
      lastName: 'Billiet',
      age: 35,
      showAge: false,
    }, this.inputState$)
  }
  
  public readonly vm$ = this.state$.pipe(map(state) => {...});
  
  public toggle(): void {
      this.patch({showAge: !this.snapshot.showAge})
  }
}

Adding more reactive stuff

In the following example we added time to show the current time every second.

import { InputState } from './input-state-decorator';
import { ObservableState } from './observable-state';

type MyUiComponentInputState = {
  firstName: string;
  lastNam: string;
  age: number;
}
type MyUiComponentState = MyUiComponentInputState & {
  showAge: number;
  time: number;
}

@Component({
  template: `
    <ng-container *ngIf="vm$|async as vm">
        <p>First Name: {{vm.firstName}}</p>
        <p>Last Name: {{vm.lastName}}</p>
        <p *ngIf="vm.showAge">Age: {{vm.age}}</p>
        The time is {{vm.time|date:'hh:mm:ss'}}
        <button (click)="toggle()">Toggle Age</button>
    </ng-container>
  `
})
export class MyUiComponent extends ObservableState<MyUiComponentState> {
  @InputState() public readonly inputState$!: Observable<MyUiComponentInputState>
  @Input() public firstName = '';
  @Input() public lastName = '';
  @Input() public age = 0;

  constructor() {
    super();
    this.initialize({
      firstName: 'Brecht',
      lastName: 'Billiet',
      age: 35,
      showAge: false,
      time: new Date().getTime()
    }, this.inputState$);
    this.connect({ time: interval(1000).pipe(map(() => new Date().getTime())) })
  }

  public readonly vm$ = this.state$;

  public toggle(): void {
    this.patch({ showAge: !this.snapshot.showAge })
  }
}

Run demo

Run backend with

json-server backend/db.json

Run frontend with

npm start