From c7f98e9521e9d22cc225cb70010c447eb300e348 Mon Sep 17 00:00:00 2001 From: Diana Lau Date: Thu, 14 Nov 2019 09:12:46 -0500 Subject: [PATCH] fix(docs): update TodoList tutorial --- docs/site/sidebars/lb4_sidebar.yml | 4 + .../todo-list/todo-list-tutorial-model.md | 60 +------ .../todo-list/todo-list-tutorial-relations.md | 155 ++++++++++++++++++ .../todo-list-tutorial-repository.md | 109 +----------- 4 files changed, 162 insertions(+), 166 deletions(-) create mode 100644 docs/site/tutorials/todo-list/todo-list-tutorial-relations.md diff --git a/docs/site/sidebars/lb4_sidebar.yml b/docs/site/sidebars/lb4_sidebar.yml index 3b7603393cdc..96102cac5d8c 100644 --- a/docs/site/sidebars/lb4_sidebar.yml +++ b/docs/site/sidebars/lb4_sidebar.yml @@ -322,6 +322,10 @@ children: url: todo-list-tutorial-repository.html output: 'web, pdf' + - title: 'Add Model Relations' + url: todo-list-tutorial-relations.html + output: 'web, pdf' + - title: 'Add TodoList Controller' url: todo-list-tutorial-controller.html output: 'web, pdf' diff --git a/docs/site/tutorials/todo-list/todo-list-tutorial-model.md b/docs/site/tutorials/todo-list/todo-list-tutorial-model.md index 9f4fbebd84ff..939de4a1763f 100644 --- a/docs/site/tutorials/todo-list/todo-list-tutorial-model.md +++ b/docs/site/tutorials/todo-list/todo-list-tutorial-model.md @@ -40,9 +40,8 @@ Enter an empty property name when done ? Enter the property name: id ? Property type: number -? Is ID field? Yes -? Required?: No -? Default value [leave blank for none]: +? Is id the ID property? Yes +? Is id generated automatically? Yes Let's add another property to TodoList Enter an empty property name when done @@ -70,61 +69,6 @@ Enter an empty property name when done Model TodoList was created in src/models/ ``` -Now that we have our new model, we need to define its relation with the `Todo` -model. Add the following import statements and property to the `TodoList` model -and update the `TodoListRelations` interface to include `todos`: - -{% include code-caption.html content="src/models/todo-list.model.ts" %} - -```ts -import {hasMany} from '@loopback/repository'; -import {Todo, TodoWithRelations} from './todo.model'; - -@model() -export class TodoList extends Entity { - // ...properties defined by the CLI... - - @hasMany(() => Todo) - todos?: Todo[]; - - // ...constructor def... -} - -export interface TodoListRelations { - todos?: TodoWithRelations[]; -} - -export type TodoListWithRelations = TodoList & TodoListRelations; -``` - -The `@hasMany()` decorator defines this property. As the decorator's name -suggests, `@hasMany()` informs LoopBack 4 that a todo list can have many todo -items. - -To complement `TodoList`'s relationship to `Todo`, we'll add in the `todoListId` -property on the `Todo` model to define the relation on both ends, along with -updating the `TodoRelations` interface to include `todoList`: - -{% include code-caption.html content="src/models/todo.model.ts" %} - -```ts -@model() -export class Todo extends Entity { - // ...properties defined by the CLI... - - @belongsTo(() => TodoList) - todoListId: number; - - // ...constructor def... -} - -export interface TodoRelations { - todoList?: TodoListWithRelations; -} - -export type TodoWithRelations = Todo & TodoRelations; -``` - Once the models have been completely configured, it's time to move on to adding a [repository](todo-list-tutorial-repository.md) for `TodoList`. diff --git a/docs/site/tutorials/todo-list/todo-list-tutorial-relations.md b/docs/site/tutorials/todo-list/todo-list-tutorial-relations.md new file mode 100644 index 000000000000..4525d5b4a464 --- /dev/null +++ b/docs/site/tutorials/todo-list/todo-list-tutorial-relations.md @@ -0,0 +1,155 @@ +--- +lang: en +title: 'Add Model Relations' +keywords: LoopBack 4.0, LoopBack 4 +sidebar: lb4_sidebar +permalink: /doc/en/lb4/todo-list-tutorial-relations.html +summary: LoopBack 4 TodoList Application Tutorial - Add TodoList Repository +--- + +### Define the model relation + +We are going to add the model relation to indicate the relation that `TodoList` +_hasMany_ `Todo` using the +[`lb4 relation` command](https://loopback.io/doc/en/lb4/Relation-generator.html). + +```sh +$ lb4 relation +? Please select the relation type hasMany +? Please select source model TodoList +? Please select target model Todo +? Foreign key name to define on the target model todoListId +? Source property name for the relation getter todos +? Allow TodoList queries to include data from related Todo instances? Yes + create src/controllers/todo-list-todo.controller.ts + +Relation HasMany was created in src/ +``` + +Now, we're going to add the relation for `Todo`. That is, `Todo` _belongsTo_ +`TodoList`. + +```sh +$ lb4 relation +? Please select the relation type belongsTo +? Please select source model Todo +? Please select target model TodoList +? Source property name for the relation getter todoListId +? Allow Todo queries to include data from related TodoList instances? Yes + create src/controllers/todo-todo-list.controller.ts + +Relation BelongsTo was created in src/ +``` + +{% include note.html content=" +we use **default** foreign key and source property names in this case. +If you'd like to customize them, please check `Relation Metadata` +https://loopback.io/doc/en/lb4/HasMany-relation.html#relation-metadata and other +relations as well. +" %} + +### Behind the scene + +If you want to understand the code changes introduced from the relation +generator command, read on the details in this section; otherwise, you are ready +to move to the next step to create the controller. + +#### Relation decorators + +When we added the `hasMany` relation using the `lb4 relation` command, it added +the `@hasMany()` decorator together with the `todos` property. As the +decorator's name suggests, `@hasMany()` informs LoopBack 4 that a todo list can +have many todo items. + +```ts +export class TodoList extends Entity { + // ...properties defined by the CLI... + + @hasMany(() => Todo) + todos?: Todo[]; + + // ...constructor def... +} +``` + +Similarly for the `belongsTo` relation: + +```ts +export class Todo extends Entity { + // ...properties of the Todo model + + @belongsTo(() => TodoList) + todoListId: number; + + // ...constructor def... +} +``` + +#### Inclusion of Related Models + +When we ran the `lb4 relation` command, we accepted the default of `Yes` to the +prompt: + +```sh +? Allow Order queries to include data from related Customer instances? (Y/n) +``` + +This registers the `inclusionResolver` for the relation(s) you were working with +above. + +Make sure to choose ‘yes’ if you’d like to use inclusion and your model is +traversable. In the example of getting the related `Todo` objects for each +`TodoList`, it registers the inclusion resolver that comes with the +[`HasManyRepositoryFactory`](https://loopback.io/doc/en/lb4/apidocs.repository.hasmanyrepository.html). + +Let's take a closer look at the `TodoListRepository`. +{% include code-caption.html content="src/repositories/todo-list.repository.ts" %} + +```ts +this.todos = this.createHasManyRepositoryFactoryFor( + 'todos', + todoRepositoryGetter, +); +// this line enables inclusion for this relation +this.registerInclusionResolver('todos', this.todos.inclusionResolver); +``` + +As a result, when you get a `TodoList`, a `todos` property will be included that +contains your related `Todo`s, for example: + +```json +{ + "id": 2, + "title": "My daily chores", + "todos": [ + { + "id": 3, + "title": "play space invaders", + "desc": "Become the very best!", + "todoListId": 2 + } + ] +} +``` + +On the other end, +[`BelongsToAccessor`](https://loopback.io/doc/en/lb4/apidocs.repository.belongstoaccessor.html) +also comes with an inclusion resolver function that we can register on the +`TodoRepository`. + +{% include code-caption.html content="src/repositories/todo.repository.ts" %} + +```ts +this.todoList = this.createBelongsToAccessorFor( + 'todoList', + todoListRepositoryGetter, +); +// this line enables inclusion for this relation +this.registerInclusionResolver('todoList', this.todoList.inclusionResolver); +``` + +### Navigation + +Previous step: [Add TodoList Repository](todo-list-tutorial-repository.md) + +Last step: [Add TodoList Controller](todo-list-tutorial-controller.md) diff --git a/docs/site/tutorials/todo-list/todo-list-tutorial-repository.md b/docs/site/tutorials/todo-list/todo-list-tutorial-repository.md index 19eb90ee53dd..42ea9f477fb5 100644 --- a/docs/site/tutorials/todo-list/todo-list-tutorial-repository.md +++ b/docs/site/tutorials/todo-list/todo-list-tutorial-repository.md @@ -37,115 +37,8 @@ bridge) Repository TodoListRepository was created in src/repositories/ ``` -From there, we'll need to make two more additions: - -- define the `todos` property, which will be used to build a constrained - `TodoRepository` -- inject `TodoRepository` instance - -Once the property type for `todos` has been defined, use -`this.createHasManyRepositoryFactoryFor` to assign it a repository constraining -factory function. Pass in the name of the relationship (`todos`) and the Todo -repository instance to constrain as the arguments for the function. - -{% include code-caption.html content="src/repositories/todo-list.repository.ts" %} - -```ts -import {Getter, inject} from '@loopback/core'; -import { - DefaultCrudRepository, - HasManyRepositoryFactory, - juggler, - repository, -} from '@loopback/repository'; -import {Todo, TodoList, TodoListRelations} from '../models'; -import {TodoRepository} from './todo.repository'; - -export class TodoListRepository extends DefaultCrudRepository< - TodoList, - typeof TodoList.prototype.id, - TodoListRelations -> { - public readonly todos: HasManyRepositoryFactory< - Todo, - typeof TodoList.prototype.id - >; - - constructor( - @inject('datasources.db') dataSource: juggler.DataSource, - @repository.getter(TodoRepository) - protected todoRepositoryGetter: Getter, - ) { - super(TodoList, dataSource); - this.todos = this.createHasManyRepositoryFactoryFor( - 'todos', - todoRepositoryGetter, - ); - } -} -``` - -### Inclusion of Related Models - -To get the related `Todo` objects for each `TodoList`, we can register the -inclusion resolver that comes with the -[`HasManyRepositoryFactory`](https://loopback.io/doc/en/lb4/apidocs.repository.hasmanyrepository.html). -We need to register this resolver to the repository class, which we can do as -follows: - -{% include code-caption.html content="src/repositories/todo-list.repository.ts" %} - -```ts -this.todos = this.createHasManyRepositoryFactoryFor( - 'todos', - todoRepositoryGetter, -); - -// Add this line to register the resolver -this.registerInclusionResolver('todos', this.todos.inclusionResolver); -``` - -Now when you get a `TodoList`, a `todos` property will be included that contains -your related `Todo`s, for example: - -```json -{ - "id": 2, - "title": "My daily chores", - "todos": [ - { - "id": 3, - "title": "play space invaders", - "desc": "Become the very best!", - "todoListId": 2 - } - ] -} -``` - -On the other end, the -[`BelongsToAccessor`](https://loopback.io/doc/en/lb4/apidocs.repository.belongstoaccessor.html) -also comes with an inclusion resolver property that we can register on the -`TodoRepository`. So, let's register this resolver to the `TodoRepository` -similar to how we did it for the `TodoListRepository`: - -{% include code-caption.html content="src/repositories/todo.repository.ts" %} - -```ts -this.todoList = this.createBelongsToAccessorFor( - 'todoList', - todoListRepositoryGetter, -); - -// Add this line to register the resolver -this.registerInclusionResolver('todoList', this.todoList.inclusionResolver); -``` - -We're now ready to expose `TodoList` and its related `Todo` API through the -[controller](todo-list-tutorial-controller.md). - ### Navigation Previous step: [Add TodoList model](todo-list-tutorial-model.md) -Last step: [Add TodoList controller](todo-list-tutorial-controller.md) +Last step: [Add Model Relations](todo-list-tutorial-relations.md)