Angular Model. Simple state management with minimalistic API, one way data flow, multiple model support and immutable data exposed as RxJS Observable.
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.
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 you AppModule
(or CoreModule
)
import { NgxModelModule } from 'ngx-model';
@NgModule({
imports: [
NgxModelModule
]
})
export class CoreModule {}
Import and use Model
and ModelFactory
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 explicitly this.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.
npm i -D @angular-extensions/schematics
ng g @angular-extensions/schematics:model --name path/my-model
ng g @angular-extensions/schematics:model --name path/my-model-collection --items
form model of collection of items