{"id":21998167,"url":"https://github.com/simmor-store/angular-simmor-examples","last_synced_at":"2026-05-02T10:32:56.953Z","repository":{"id":38678047,"uuid":"211906484","full_name":"simmor-store/angular-simmor-examples","owner":"simmor-store","description":"An example of how to use simmor with Angular","archived":false,"fork":false,"pushed_at":"2023-01-07T10:15:00.000Z","size":1868,"stargazers_count":0,"open_issues_count":27,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-23T05:11:14.531Z","etag":null,"topics":["angular","immer","rxjs","simmor"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/simmor-store.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-09-30T16:38:49.000Z","updated_at":"2019-10-10T18:27:17.000Z","dependencies_parsed_at":"2023-02-06T21:32:04.839Z","dependency_job_id":null,"html_url":"https://github.com/simmor-store/angular-simmor-examples","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/simmor-store/angular-simmor-examples","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simmor-store%2Fangular-simmor-examples","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simmor-store%2Fangular-simmor-examples/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simmor-store%2Fangular-simmor-examples/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simmor-store%2Fangular-simmor-examples/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/simmor-store","download_url":"https://codeload.github.com/simmor-store/angular-simmor-examples/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simmor-store%2Fangular-simmor-examples/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32531736,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-02T01:12:54.858Z","status":"online","status_checked_at":"2026-05-02T02:00:05.923Z","response_time":132,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","immer","rxjs","simmor"],"created_at":"2024-11-29T22:20:18.998Z","updated_at":"2026-05-02T10:32:56.937Z","avatar_url":"https://github.com/simmor-store.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"Simmor is a simple immutable boilerplate-free framework-agnostic store. \n\n[https://github.com/simmor-store/simmor](https://github.com/simmor-store/simmor)\n\nThis repository is an example of how to use it with Angular.\n\n# Install\n```\nnpm install simmor\n```\nSimmor uses `rxjs` internally so it doesn't require additional packages and can be used with `async` pipe.\n\n# Store example\nAssume, we have this simple service\n```ts\n@Injectable({providedIn: 'root'})\nexport class CounterService {\n  getValue() {\n    return of(123).pipe(delay(300));\n  }\n}\n```\nAnd we want to create a store with state like this\n```ts\nexport interface CounterState {\n  value: number;\n}\n\nconst initialState: CounterState = {\n  value: 0\n}\n```\n\nWe can define a store class. State can be modified throw `draft` field. Simmor uses [immer](https://github.com/immerjs/immer) that can update immutable state by mutating it.\n\n```ts\n@Injectable({providedIn: 'root'})\nexport class CounterStore extends ReducerStore\u003cCounterState\u003e {\n\n  constructor(private counterService: CounterService) {\n    super(initialState, {\n      middlewares: [createLocalStorageMiddleware('counter')]\n    });\n  }\n\n  increase() {\n    this.draft.value += 1;\n  }\n\n  decrease() {\n    const newValue = this.draft.value - 1\n    if (newValue \u003e= 0) {\n      this.draft.value = newValue;\n    }\n  }\n\n  setValue(value: number) {\n    this.draft.value = value;\n  }\n\n  setValueAsync() {\n    this.counterService.getValue().subscribe(value =\u003e {\n      this.setValue(value);\n    });\n  }\n}\n\n```\n\nNow we can use our store in a component like this\n\n```ts\n@Component({\n  selector: 'app-counter',\n  templateUrl: './counter.component.html',\n  styleUrls: ['./counter.component.scss'],\n  changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class CounterComponent implements OnInit {\n\n  constructor(private store: CounterStore) { }\n\n  ngOnInit() { }\n\n}\n\n```\n```html\n\u003cdiv *ngIf=\"store.state$ | async as state\" class=\"counter\"\u003e\n  \u003cspan\u003e{{state.value}}\u003c/span\u003e\n  \u003cbutton (click)=\"store.increase()\"\u003e+\u003c/button\u003e\n  \u003cbutton (click)=\"store.decrease()\"\u003e-\u003c/button\u003e\n  \u003cbutton (click)=\"store.setValue(0)\"\u003eReset\u003c/button\u003e\n  \u003cbutton (click)=\"store.setValueAsync()\"\u003eSet value async\u003c/button\u003e\n\u003c/div\u003e\n```\n# Middlewares\nSimmor supports middlewares. Here an example of middleware that saves state to localStorage.\n```ts\nexport function createLocalStorageMiddleware(key: string): Middleware {\n  return next =\u003e action =\u003e {\n    const newState = next(action)\n    if (action.methodName === \"constructor\") {\n      const savedState = localStorage.getItem(key)\n      if (savedState) {\n        return JSON.parse(savedState)\n      }\n    }\n    localStorage.setItem(key, JSON.stringify(newState))\n    return newState\n  }\n}\n\n```\n\nWe can pass middlewares in the constructor of the store and our component can now save its state between sessions.\n\n```ts\n@Injectable({providedIn: 'root'})\nexport class CounterStore extends ReducerStore\u003cCounterState\u003e {\n  constructor(private counterService: CounterService) {\n    super(initialState, {\n      middlewares: [createLocalStorageMiddleware('counter')]\n    });\n  }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimmor-store%2Fangular-simmor-examples","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimmor-store%2Fangular-simmor-examples","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimmor-store%2Fangular-simmor-examples/lists"}