@loopback/docs
Version:
Documentation files rendered at [https://loopback.io](https://loopback.io)
208 lines (170 loc) • 6.38 kB
Markdown
---
lang: en
title: "Add TodoList and TodoList's Todo Controller"
keywords: LoopBack 4.0, LoopBack 4, Node.js, TypeScript, OpenAPI, Tutorial
sidebar: lb4_sidebar
permalink: /doc/en/lb4/todo-list-tutorial-controller.html
summary:
LoopBack 4 TodoList Application Tutorial - Add TodoList and TodoList's Todo
Controller
---
### Controllers with related models
Defining business logic to handle requests to related models isn't too different
from handling requests for standalone models. We'll create
[controllers](../../Controller.md) to handle requests for todo-lists and todo
items under a todo-list.
### Create TodoList controller
Run the CLI command for creating a RESTful CRUD controller for our `TodoList`
routes with the following inputs:
```sh
$ lb4 controller
? Controller class name: TodoList
Controller TodoList will be created in src/controllers/todo-list.controller.ts
? What kind of controller would you like to generate? REST Controller with CRUD functions
? What is the name of the model to use with this CRUD repository? TodoList
? What is the name of your CRUD repository? TodoListRepository
? What is the name of ID property? id
? What is the type of your ID? number
? Is the id omitted when creating a new instance? Yes
? What is the base HTTP path name of the CRUD operations? /todo-lists
create src/controllers/todo-list.controller.ts
update src/controllers/index.ts
Controller TodoList was created in src/controllers/
```
To view the completed file, see the
[`TodoList` example](https://github.com/loopbackio/loopback-next/blob/master/examples/todo-list/src/controllers/todo-list.controller.ts).
And voilà! We now have a set of basic APIs for todo-lists, just like that!
#### Inclusion of Related Models
In order to get our related `Todo`s for each `TodoList`, let's update the
`schema`.
In `src/controllers/todo-list.controller.ts`, first import `getModelSchemaRef`
from `@loopback/rest`.
Then update the following `schema`s in `responses`'s `content`:
{% include code-caption.html content="src/controllers/todo-list.controller.ts" %}
```ts
('/todo-lists', {
responses: {
'200': {
description: 'Array of TodoList model instances',
content: {
'application/json': {
schema: {
type: 'array',
items: getModelSchemaRef(TodoList, {includeRelations: true}),
},
},
},
},
},
})
async find(/*...*/) {/*...*/}
('/todo-lists/{id}', {
responses: {
'200': {
description: 'TodoList model instance',
content: {
'application/json': {
schema: getModelSchemaRef(TodoList, {includeRelations: true}),
},
},
},
},
})
async findById(/*...*/) {/*...*/}
```
Let's also update it in the `TodoController`:
{% include code-caption.html content="src/controllers/todo.controller.ts" %}
```ts
('/todos', {
responses: {
'200': {
description: 'Array of Todo model instances',
content: {
'application/json': {
schema: {
type: 'array',
items: getModelSchemaRef(Todo, {includeRelations: true}),
},
},
},
},
},
})
async findTodos(/*...*/) {/*...*/}
('/todos/{id}', {
responses: {
'200': {
description: 'Todo model instance',
content: {
'application/json': {
schema: getModelSchemaRef(Todo, {includeRelations: true}),
},
},
},
},
})
async findTodoById(/*...*/) {/*...*/}
```
#### Relation Controllers
Earlier when we used `lb4 relation` to create the two relations between `Todo`
and `TodoList`, you may have noticed
`src/controllers/todo-todo-list.controller.ts` and
`src/controllers/todo-list-todo.controller.ts` were created. These files contain
a set of API for the relations.
Relation controllers act in a similar manner to normal controllers, except they
modify the relational property. For example, in the
`src/controllers/todo-list-todo.controller.ts` file, we can do requests to the
endpoint `/todo-lists/{id}/todos`, which we'll see in the
[Try it out](#try-it-out) section.
As `src/controllers/todo-todo-list.controller.ts` only contains one method, we
can move it to the `Todo` controller and delete that file:
{% include code-caption.html content="src/controllers/todo.controller.ts" %}
```ts
export class TodoController {
constructor() {} // ...
// other controller methods
('/todos/{id}/todo-list', {
responses: {
'200': {
description: 'TodoList belonging to Todo',
content: {
'application/json': {
schema: {type: 'array', items: getModelSchemaRef(TodoList)},
},
},
},
},
})
async getTodoList(
.path.number('id') id: typeof Todo.prototype.id,
): Promise<TodoList> {
return this.todoRepository.todoList(id);
}
}
```
### Try it out
With the controllers complete, your application is ready to start up again!
`/boot` should wire up everything for us when we start the application,
so there's nothing else we need to do before we try out our new routes.
```sh
$ npm start
Server is running at http://127.0.0.1:3000
```
{% include note.html content="
When using the API Explorer, be sure to clear out any default <i><b>filter</b></i> or <i><b>where</b></i> objects in order to see all the data." %}
Here are some new requests you can try out:
- `POST /todo-lists` with a body of `{ "title": "grocery list" }`.
- `POST /todo-lists/{id}/todos` using the ID you got back from the previous
`POST` request and this body: `{ "title": "get eggs", "isComplete": false}`.
Notice that response body you get back contains property `todoListId` with the
ID from before.
- `GET /todo-lists/{id}/todos` with the ID from before, and see if you get the
todo you created from before.
- `GET /todo-lists/{id}` with the ID from before, with the following filter
`{"include": [{"relation": "todos"}]}`, and see if you get a `todos` property
with the todo created before. You can also use the following url to test this
endpoint (remember to replace `{id}` with the ID from before):
http://localhost:3000/todo-lists/{id}?filter[include][][relation]=todos
And there you have it! You now have the power to define APIs for related models!
### Navigation
Previous step: [Add Model Relations](todo-list-tutorial-relations.md)