docs/site/tutorials/todo-list/todo-list-tutorial-controller.md
Defining business logic to handle requests to related models isn't too different from handling requests for standalone models. We'll create controllers to handle requests for todo-lists and todo items under a todo-list.
Run the CLI command for creating a RESTful CRUD controller for our TodoList
routes with the following inputs:
$ 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.
And voilà! We now have a set of basic APIs for todo-lists, just like that!
In order to get our related Todos 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 schemas in responses's content:
{% include code-caption.html content="src/controllers/todo-list.controller.ts" %}
@get('/todo-lists', {
responses: {
'200': {
description: 'Array of TodoList model instances',
content: {
'application/json': {
schema: {
type: 'array',
items: getModelSchemaRef(TodoList, {includeRelations: true}),
},
},
},
},
},
})
async find(/*...*/)
@get('/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" %}
@get('/todos', {
responses: {
'200': {
description: 'Array of Todo model instances',
content: {
'application/json': {
schema: {
type: 'array',
items: getModelSchemaRef(Todo, {includeRelations: true}),
},
},
},
},
},
})
async findTodos(/*...*/)
@get('/todos/{id}', {
responses: {
'200': {
description: 'Todo model instance',
content: {
'application/json': {
schema: getModelSchemaRef(Todo, {includeRelations: true}),
},
},
},
},
})
async findTodoById(/*...*/)
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 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" %}
export class TodoController {
constructor() {} // ...
// other controller methods
@get('/todos/{id}/todo-list', {
responses: {
'200': {
description: 'TodoList belonging to Todo',
content: {
'application/json': {
schema: {type: 'array', items: getModelSchemaRef(TodoList)},
},
},
},
},
})
async getTodoList(
@param.path.number('id') id: typeof Todo.prototype.id,
): Promise<TodoList> {
return this.todoRepository.todoList(id);
}
}
With the controllers complete, your application is ready to start up again!
@loopback/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.
$ 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]=todosAnd there you have it! You now have the power to define APIs for related models!
Previous step: Add Model Relations