Skip to content

Commit d81d249

Browse files
committed
fix(docs): adjust readme content to reflect new implementation
1 parent 28197e5 commit d81d249

File tree

1 file changed

+123
-82
lines changed

1 file changed

+123
-82
lines changed

README.md

Lines changed: 123 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -7,120 +7,161 @@ by [@tomastrajan](https://twitter.com/tomastrajan)
77
Simple state management with minimalistic API, one way data flow,
88
multiple model support and immutable data exposed as RxJS Observable.
99

10-
## Documentation
10+
* [Changelog](https://github.com/angular-extensions/model/blob/master/CHANGELOG.md)
1111

12-
- [StackBlitz Demo](https://stackblitz.com/github/tomastrajan/ngx-model-example)
13-
- [Demo & Documentation](http://tomastrajan.github.io/angular-model-pattern-example/)
14-
- [Blog Post](https://medium.com/@tomastrajan/model-pattern-for-angular-state-management-6cb4f0bfed87)
15-
- [Changelog](https://github.com/angular-extensions/model/blob/master/CHANGELOG.md)
12+
## Documentation
1613

1714
![@angular-extensions/model dataflow diagram](https://raw.githubusercontent.com/tomastrajan/angular-model-pattern-example/master/src/assets/model_graph.png 'ngx-model dataflow diagram')
1815

19-
## Getting started
16+
## Getting started in Angular CLI projects
2017

21-
1. Install `@angular-extensions/model`
18+
1. Install `@angular-extensions/model` library
2219

2320
```
2421
ng add @angular-extensions/model
2522
```
23+
24+
2. Generate model service
25+
```
26+
ng g @angular-extensions/model:model examples/todo --items
27+
```
2628
27-
2. Import and use `Model` and `ModelFactory` in your own services or generate new service using schematics (see below)
28-
29+
3. Use model service in your component. Let's generate new `todo` component
30+
```
31+
ng g component examples/todo --inline-template
32+
```
33+
And then adjust component implementation as in the example below
2934
```ts
30-
import { Injectable } from '@angular/core';
31-
import { Observable } from 'rxjs';
32-
import { ModelFactory, Model } from '@angular-extensions/model';
33-
34-
@Injectable()
35-
export class TodosService {
36-
private model: Model<Todo[]>;
37-
38-
todos$: Observable<Todo[]>;
39-
40-
constructor(private modelFactory: ModelFactory<Todo[]>) {
41-
this.model = this.modelFactory.create([]); // create model and pass initial data
42-
this.todos$ = this.model.data$; // expose model data as named public property
35+
import { Component } from '@angular/core';
36+
import { TodoService } from './todo.service';
37+
38+
@Component({
39+
selector: 'app-todo',
40+
template: `
41+
<!-- template subscription to todos using async pipe -->
42+
<ng-container *ngIf="todoService.todos$ | async as todos">
43+
<h1>Todos ({{todos.length}})</h1>
44+
<ul>
45+
<li *ngFor="let todo of todos">
46+
{{todo.prop}}
47+
</li>
48+
</ul>
49+
<button (click)="addTodo()">Add todo</button>
50+
</ng-container>
51+
`,
52+
styleUrls: ['./todo.component.css']
53+
})
54+
export class TodoComponent {
55+
56+
constructor(public todoService: TodoService) { }
57+
58+
addTodo() {
59+
this.todoService.addTodo({ prop: 'New todo!' });
4360
}
61+
62+
}
4463
45-
toggleTodo(id: string) {
46-
// retrieve raw model data
47-
const todos = this.model.get();
64+
```
65+
4. Use our new `<app-todo></app-todo>` component in the template of the `app.component.html`
66+
67+
Please mind that you might be using different application prefix than `app-` o adjust accordingly.
68+
69+
## Model API
70+
The model has a small API that as shown in in the illustration above.
4871
49-
// mutate model data
50-
todos.forEach(t => {
51-
if (t.id === id) {
52-
t.done = !t.done;
53-
}
54-
});
72+
* `get(): T` - returns current model value
73+
* `set(data: T): void` - sets new model value
74+
* `data$: Observable<T>` - observable of the model data, every call `set(newData)` will push new model state to to this observable (the data is **immutable by default** but this can be changed using one of the other provided factory functions as described below)
5575
56-
// set new model data (after mutation)
57-
this.model.set(todos);
58-
}
59-
}
60-
```
76+
Check out generated `todo.service.ts` to see an example of how the model should be used.
77+
In general, the service will implement methods in which it will retrieve current model state, mutate it and set new state back to the model.
78+
Model will then take care of pushing immutable copies of the new state to all components which are subscribed using `data$`.
6179
62-
3. Use service in your component. Import and inject service into components constructor.
63-
Subscribe to services data in template `todosService.todos$ | async`
64-
or explicitly `this.todosService.todos$.subscribe(todos => { /* ... */ })`
80+
#### Available Model Factories
6581
66-
```ts
67-
import { Component, OnInit, OnDestroy } from '@angular/core';
68-
import { Subject } from 'rxjs';
82+
Models are created using model factory as shown in example `todo.service.ts`, check line `this.model = this.modelFactory.create(initialData);`.
83+
Multiple model factories are provided out of the box to support different use cases:
6984
70-
import { TodosService, Todo } from './todos.service';
85+
- `create(initialData: T): Model<T>` - create basic model which is immutable by default (`JSON` cloning)
86+
- `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 skipped
87+
- `createMutableWithSharedSubscription(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)
88+
- `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)
7189
72-
@Component({
73-
selector: 'model-todos',
74-
templateUrl: `
75-
/* ... */
76-
<!-- template subscription to todos using async pipe -->
77-
<ng-container *ngId="todosService.todos$ | async as todos">
78-
<h1>Todos ({{todos.count}})</h1>
79-
<ul>
80-
<li *ngFor="let todo of todos" (click)="onTodoClick(todo)">
81-
{{todo.name}}
82-
</li>
83-
</ul>
84-
</ng-container>
85-
`,
86-
})
87-
export class TodosComponent implements OnInit {
8890
89-
count: number;
91+
## Model Schematics API
9092
91-
constructor(public todosService: TodosService) {}
93+
Model services are generated using Angular CLI. It is a 3rd party schematics so we have to
94+
specify it when running `ng g` command like this `ng g @angular-extensions/model:<schematics-name> <schematics parameters>`.
95+
The schematics currently contains only one schematic called `model`.
9296
93-
onTodoClick(todo: Todo) {
94-
this.todosService.toggleTodo(todo.id);
95-
}
97+
#### Basic usage
98+
```
99+
ng g @angular-extensions/model:model example/todo
100+
```
96101
97-
}
102+
#### Supported options
98103
99-
```
104+
* `--items` - creates service for collection of items (it will expose `todos$: Observable<Todo[]>;` instead of `todo$: Observable<Todo>`)
105+
* `--flat` - generates service file directly in the`examples` folder without creating folder with the name `todos` (default: `false`)
106+
* `--spec` - generate service test file (default: `true`)
107+
* `--module` - will decide how to register service into Angular dependency injection context (service will use `providedIn: 'root'` when no module was provided, module can be provided as a path to module relative to the location of generated service, eg `ng g @angular-extensions/model:model examples/auth --module ../app.module.ts`)
108+
* `--project` - project in which to generate the service (for multi project Angular CLI workspaces, will generate service in the first project by default, when no project was provided)
100109
101-
## Available Model Factories
110+
111+
## Getting started without Angular CLI
112+
It is also possible to use `@angular-extensions/model` in Angular project which do not use Angular CLI.
113+
1. Install `@angular-extensions/model` library
102114
103-
Models are created using model factory as shown in above example `this.model = this.modelFactory.create([]);`.
104-
Multiple model factories are provided out of the box to support different use cases:
115+
```
116+
npm i -S @angular-extensions/model
117+
```
118+
119+
2. Create new model service in `src/app/examples/todo/todo.service.ts`
120+
```ts
121+
import { Injectable } from '@angular/core';
122+
import { Model, ModelFactory } from '@angular-extensions/model';
123+
import { Observable } from 'rxjs';
124+
125+
const initialData: Todo[] = [];
126+
127+
128+
@Injectable({
129+
providedIn: 'root'
130+
})
131+
export class TodoService {
132+
private model: Model<Todo[]>;
133+
134+
todos$: Observable<Todo[]>;
135+
136+
constructor(private modelFactory: ModelFactory<Todo[]>) {
137+
this.model = this.modelFactory.create(initialData);
138+
this.todos$ = this.model.data$;
139+
}
140+
141+
addTodo(todo: Todo) {
142+
const todos = this.model.get();
143+
144+
todos.push(todo);
145+
146+
this.model.set(todos);
147+
}
148+
}
149+
150+
export interface Todo {
151+
prop: string;
152+
}
153+
```
154+
155+
3. Use new model service in some of your components as described in point 3 and above in `Getting started in Angular CLI projects` section
105156
106-
- `create(initialData: T): Model<T>` - create basic model which is immutable by default (`JSON` cloning)
107-
- `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 skipped
108-
- `createMutableWithSharedSubscription(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)
109-
- `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)
110157
111-
## Relationship to Angular Model Pattern
158+
## Relationship to older Angular Model Pattern and `ngx-model` library
112159
113-
This is a library version of [Angular Model Pattern](https://tomastrajan.github.io/angular-model-pattern-example).
160+
This is a new enhanced version of older library called `ngx-model` which was in turn implementation of [Angular Model Pattern](https://tomastrajan.github.io/angular-model-pattern-example).
114161
All the original examples and documentation are still valid. The only difference is that
115-
you can add `@angular-extensions/model` with `ng add` instead of having to copy model pattern
162+
you can add `@angular-extensions/model` with `ng add` instead of installing `ngx-model` or having to copy model pattern
116163
implementation to your project manually.
117164
118165
Check out the [Blog Post](https://medium.com/@tomastrajan/model-pattern-for-angular-state-management-6cb4f0bfed87) and
119166
[Advanced Usage Patterns](https://tomastrajan.github.io/angular-model-pattern-example#/advanced)
120167
for more how-tos and examples.
121-
122-
## Getting started with Schematics
123-
124-
The `@angular-extensions/model` comes with schematics out of the box!
125-
Run `ng g @angular-extensions/model:model path/to/my-model` to generate model service and corresponding tests.
126-
Use `--items` flag if you want ot generate model service for a collection

0 commit comments

Comments
 (0)