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 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:
$ 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!
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
:
@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
:
@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(/*...*/) {/*...*/}
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 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:
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);
}
}
Try it out
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
Note:
When using the API Explorer, be sure to clear out any default filter or where 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 previousPOST
request and this body:{ "title": "get eggs", "isComplete": false}
. Notice that response body you get back contains propertytodoListId
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 atodos
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