Skip to content

Commit 84b7b02

Browse files
authored
Merge pull request abpframework#3734 from abpframework/docs/bookstore-tutorial
Docs: Used generate proxy command on the BookStore tutorial
2 parents f0e8080 + 5e4fab7 commit 84b7b02

File tree

5 files changed

+258
-388
lines changed

5 files changed

+258
-388
lines changed

docs/en/Tutorials/Part-1.md

+57-93
Original file line numberDiff line numberDiff line change
@@ -877,94 +877,51 @@ Run the following command in the terminal to create a new state, named `BooksSta
877877
![Initial book list page](./images/bookstore-generate-state-books.png)
878878

879879
```bash
880-
yarn ng generate ngxs-schematic:state books
880+
npx @ngxs/cli --name books --directory src/app/books
881881
```
882882

883-
* This command creates several new files and updates `app.modules.ts` file to import the `NgxsModule` with the new state.
883+
* This command creates `books.state.ts` and `books.actions.ts` files in the `src/app/books/state` folder. See the [NGXS CLI documentation](https://www.ngxs.io/plugins/cli).
884884

885-
#### Get books data from backend
886-
887-
Create data types to map the data from the backend (you can check Swagger UI or your backend API to see the data format).
888-
889-
![BookDto properties](./images/bookstore-swagger-book-dto-properties.png)
890-
891-
Open the `books.ts` file in the `app\store\models` folder and replace the content as below:
885+
Import the `BooksState` to the `app.module.ts` in the `src/app` folder and then add the `BooksState` to `forRoot` static method of `NgxsModule` as an array element of the first parameter of the method.
892886

893887
```js
894-
export namespace Books {
895-
export interface State {
896-
books: Response;
897-
}
888+
// ...
889+
import { BooksState } from './books/state/books.state'; //<== imported BooksState ==>
898890

899-
export interface Response {
900-
items: Book[];
901-
totalCount: number;
902-
}
891+
@NgModule({
892+
imports: [
893+
// other imports
903894

904-
export interface Book {
905-
name: string;
906-
type: BookType;
907-
publishDate: string;
908-
price: number;
909-
lastModificationTime: string;
910-
lastModifierId: string;
911-
creationTime: string;
912-
creatorId: string;
913-
id: string;
914-
}
895+
NgxsModule.forRoot([BooksState]), //<== added BooksState ==>
915896

916-
export enum BookType {
917-
Undefined,
918-
Adventure,
919-
Biography,
920-
Dystopia,
921-
Fantastic,
922-
Horror,
923-
Science,
924-
ScienceFiction,
925-
Poetry,
926-
}
927-
}
897+
//other imports
898+
],
899+
// ...
900+
})
901+
export class AppModule {}
928902
```
929903

930-
* Added `Book` interface that represents a book object and `BookType` enum which represents a book category.
904+
#### Generate proxies
931905

932-
#### BooksService
906+
ABP CLI provides `generate-proxy` command that generates client proxies for your HTTP APIs to make easy to consume your services from the client side. Before running generate-proxy command, your host must be up and running. See the [CLI documentation](../CLI.md)
933907

934-
Create a new service, named `BooksService` to perform `HTTP` calls to the server:
908+
Run the following command in the `angular` folder:
935909

936910
```bash
937-
yarn ng generate service books/shared/books
911+
abp generate-proxy --module app
938912
```
939913

940-
![service-terminal-output](./images/bookstore-service-terminal-output.png)
914+
![Generate proxy command](./images/generate-proxy-command.png)
941915

942-
Open the `books.service.ts` file in `app\books\shared` folder and replace the content as below:
916+
The generated files looks like below:
943917

944-
```js
945-
import { Injectable } from '@angular/core';
946-
import { RestService } from '@abp/ng.core';
947-
import { Books } from '../../store/models';
948-
import { Observable } from 'rxjs';
918+
![Generated files](./images/generated-proxies.png)
949919

950-
@Injectable({
951-
providedIn: 'root',
952-
})
953-
export class BooksService {
954-
constructor(private restService: RestService) {}
955-
956-
get(): Observable<Books.Response> {
957-
return this.restService.request<void, Books.Response>({
958-
method: 'GET',
959-
url: '/api/app/book'
960-
});
961-
}
962-
}
963-
```
920+
#### GetBooks Action
964921

965-
* We added the `get` method to get the list of books by performing an HTTP request to the related endpoint.
922+
Actions can either be thought of as a command which should trigger something to happen, or as the resulting event of something that has already happened. [See NGXS Actions documentation](https://www.ngxs.io/concepts/actions).
966923

967-
Open the`books.actions.ts` file in `app\store\actions` folder and replace the content below:
924+
Open the `books.actions.ts` file in `app/books/state` folder and replace the content below:
968925

969926
```js
970927
export class GetBooks {
@@ -974,43 +931,48 @@ export class GetBooks {
974931

975932
#### Implement BooksState
976933

977-
Open the `books.state.ts` file in `app\store\states` folder and replace the content below:
934+
Open the `books.state.ts` file in `app/books/state` folder and replace the content below:
978935

979936
```js
937+
import { PagedResultDto } from '@abp/ng.core';
980938
import { State, Action, StateContext, Selector } from '@ngxs/store';
981-
import { GetBooks } from '../actions/books.actions';
982-
import { Books } from '../models/books';
983-
import { BooksService } from '../../books/shared/books.service';
939+
import { GetBooks } from './books.actions';
940+
import { BookService } from '../../app/shared/services';
984941
import { tap } from 'rxjs/operators';
985942
import { Injectable } from '@angular/core';
943+
import { BookDto } from '../../app/shared/models';
986944

987-
@State<Books.State>({
945+
export class BooksStateModel {
946+
public book: PagedResultDto<BookDto>;
947+
}
948+
949+
@State<BooksStateModel>({
988950
name: 'BooksState',
989-
defaults: { books: {} } as Books.State,
951+
defaults: { book: {} } as BooksStateModel,
990952
})
991953
@Injectable()
992954
export class BooksState {
993955
@Selector()
994-
static getBooks(state: Books.State) {
995-
return state.books.items || [];
956+
static getBooks(state: BooksStateModel) {
957+
return state.book.items || [];
996958
}
997959

998-
constructor(private booksService: BooksService) {}
960+
constructor(private bookService: BookService) {}
999961

1000962
@Action(GetBooks)
1001-
get(ctx: StateContext<Books.State>) {
1002-
return this.booksService.get().pipe(
1003-
tap(booksResponse => {
963+
get(ctx: StateContext<BooksStateModel>) {
964+
return this.bookService.getListByInput().pipe(
965+
tap((booksResponse) => {
1004966
ctx.patchState({
1005-
books: booksResponse,
967+
book: booksResponse,
1006968
});
1007-
}),
969+
})
1008970
);
1009971
}
1010972
}
1011973
```
1012-
1013-
* We added the `GetBooks` action that retrieves the books data via `BooksService` and patches the state.
974+
* We added the book property to BooksStateModel model.
975+
* We added the `GetBooks` action that retrieves the books data via `BooksService` that generated via ABP CLI and patches the state.
1014976
* `NGXS` requires to return the observable without subscribing it in the get function.
1015977

1016978
#### BookListComponent
@@ -1019,11 +981,12 @@ Open the `book-list.component.ts` file in `app\books\book-list` folder and repla
1019981

1020982
```js
1021983
import { Component, OnInit } from '@angular/core';
1022-
import { Store, Select } from '@ngxs/store';
1023-
import { BooksState } from '../../store/states';
984+
import { Select, Store } from '@ngxs/store';
1024985
import { Observable } from 'rxjs';
1025-
import { Books } from '../../store/models';
1026-
import { GetBooks } from '../../store/actions';
986+
import { finalize } from 'rxjs/operators';
987+
import { BookDto, BookType } from '../../app/shared/models';
988+
import { GetBooks } from '../state/books.actions';
989+
import { BooksState } from '../state/books.state';
1027990

1028991
@Component({
1029992
selector: 'app-book-list',
@@ -1032,23 +995,24 @@ import { GetBooks } from '../../store/actions';
1032995
})
1033996
export class BookListComponent implements OnInit {
1034997
@Select(BooksState.getBooks)
1035-
books$: Observable<Books.Book[]>;
998+
books$: Observable<BookDto[]>;
1036999

1037-
booksType = Books.BookType;
1000+
booksType = BookType;
10381001

10391002
loading = false;
10401003

1041-
constructor(private store: Store) { }
1004+
constructor(private store: Store) {}
10421005

10431006
ngOnInit() {
10441007
this.get();
10451008
}
10461009

10471010
get() {
10481011
this.loading = true;
1049-
this.store.dispatch(new GetBooks()).subscribe(() => {
1050-
this.loading = false;
1051-
});
1012+
this.store
1013+
.dispatch(new GetBooks())
1014+
.pipe(finalize(() => (this.loading = false)))
1015+
.subscribe(() => {});
10521016
}
10531017
}
10541018
```

0 commit comments

Comments
 (0)