Please use new @angular-extensions/model
package / repo which is a combination of both the model library and related schematics which renders this package uselsess. On the other hand, feel free to keep using ngx-model
if it suits your needs, it will not be deleted, but there will be no further development. Please, have a look into migration section in the new documentation.
by @tomastrajan
Simple state management with minimalistic API, one way data flow, multiple model support and immutable data exposed as RxJS Observable.
- StackBlitz Demo
- Demo & Documentation
- Blog Post
- Changelog
- Schematics - generate
ngx-model
services using Angular CLI schematics!
-
Install
ngx-model
npm install --save ngx-model
or
yarn add ngx-model
-
Import and use
NgxModelModule
in youAppModule
(orCoreModule
)import { NgxModelModule } from 'ngx-model'; @NgModule({ imports: [ NgxModelModule ] }) export class CoreModule {}
-
Import and use
Model
andModelFactory
in your own services.import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { ModelFactory, Model } from 'ngx-model'; @Injectable() export class TodosService { private model: Model<Todo[]>; todos$: Observable<Todo[]>; constructor(private modelFactory: ModelFactory<Todo[]>) { this.model = this.modelFactory.create([]); // create model and pass initial data this.todos$ = this.model.data$; // expose model data as named public property } toggleTodo(id: string) { // retrieve raw model data const todos = this.model.get(); // mutate model data todos.forEach(t => { if (t.id === id) { t.done = !t.done; } }); // set new model data (after mutation) this.model.set(todos); } }
-
Use service in your component. Import and inject service into components constructor. Subscribe to services data in template
todosService.todos$ | async
or explicitlythis.todosService.todos$.subscribe(todos => { /* ... */ })
import { Component, OnInit, OnDestroy } from '@angular/core'; import { Subject } from 'rxjs'; import { TodosService, Todo } from './todos.service'; @Component({ selector: 'ngx-model-todos', templateUrl: ` /* ... */ <h1>Todos ({{count}})</h1> <ul> <!-- template subscription to todos using async pipe --> <li *ngFor="let todo of todosService.todos$ | async" (click)="onTodoClick(todo)"> {{todo.name}} </li> </ul> `, }) export class TodosComponent implements OnInit, OnDestroy { private unsubscribe$: Subject<void> = new Subject<void>(); count: number; constructor(public todosService: TodosService) {} ngOnInit() { // explicit subscription to todos to get count this.todosService.todos .pipe( takeUntil(this.unsubscribe$) // declarative unsubscription ) .subscribe(todos => this.count = todos.length); } ngOnDestroy(): void { // for declarative unsubscription this.unsubscribe$.next(); this.unsubscribe$.complete(); } onTodoClick(todo: Todo) { this.todosService.toggleTodo(todo.id); } }
Models are created using model factory as shown in above example this.model = this.modelFactory.create([]);
.
Multiple model factories are provided out of the box to support different use cases:
create(initialData: T): Model<T>
- create basic model which is immutable by default (JSON
cloning)createMutable(initialData: T): Model<T>
- create model with no immutability guarantees (you have to make sure that model consumers don't mutate and corrupt model state) but much more performance because whole cloning step is skippedcreateMutableWithSharedSubscription(initialData: T): Model<T>
- gain even more performance by skipping both immutability and sharing subscription between all consumers (eg situation in which many components are subscribed to single model)createWithCustomClone(initialData: T, clone: (data: T) => T)
- create immutable model by passing your custom clone function (JSON
cloning doesn't support properties containing function or regex so custom cloning functionality might be needed)
This is a library version of Angular Model Pattern.
All the original examples and documentation are still valid. The only difference is that
you can install ngx-model
from npm instead of having to copy model pattern
implementation to your project manually.
Check out the Blog Post and Advanced Usage Patterns for more how-tos and examples.
- make sure you're using this in project generated with Angular CLI.
- install dependency with
npm i -D @angular-extensions/schematics
- generate model services with
ng g @angular-extensions/schematics:model --name path/my-model
- or with
ng g @angular-extensions/schematics:model --name path/my-model-collection --items
form model of collection of items - add your own model service methods and tests