Skip to content

Commit

Permalink
docs: update todo-list example
Browse files Browse the repository at this point in the history
  • Loading branch information
nabdelgadir committed Jan 14, 2020
1 parent 52a6d71 commit 91bd544
Show file tree
Hide file tree
Showing 12 changed files with 440 additions and 199 deletions.
4 changes: 4 additions & 0 deletions docs/site/sidebars/lb4_sidebar.yml
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,10 @@ children:
url: todo-list-tutorial-relations.html
output: 'web, pdf'

- title: 'Add a HasOne Relation'
url: todo-list-tutorial-has-one-relation.html
output: 'web, pdf'

- title: 'Add TodoList Controller'
url: todo-list-tutorial-controller.html
output: 'web, pdf'
Expand Down
190 changes: 21 additions & 169 deletions docs/site/tutorials/todo-list/todo-list-tutorial-controller.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Controller TodoList will be created in src/controllers/todo-list.controller.ts
? 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
Expand Down Expand Up @@ -122,193 +123,44 @@ async findTodos(/*...*/) {/*...*/}
async findTodoById(/*...*/) {/*...*/}
```

### Create TodoList's Todo controller
#### Relation Controllers

For the controller handling `Todos` of a `TodoList`, we'll start with an empty
controller:
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.conrtoller.ts` were created. These files contain
a set of API for the relations.

```sh
$ lb4 controller
? Controller class name: TodoListTodo
Controller TodoListTodo will be created in src/controllers/todo-list-todo.controller.ts

? What kind of controller would you like to generate? Empty Controller
create src/controllers/todo-list-todo.controller.ts
update src/controllers/index.ts

Controller TodoListTodo was created in src/controllers/
```

Let's add in an injection for our `TodoListRepository`:

{% include code-caption.html content="src/controllers/todo-list-todo.controller.ts" %}

```ts
import {repository} from '@loopback/repository';
import {TodoListRepository} from '../repositories';

export class TodoListTodoController {
constructor(
@repository(TodoListRepository) protected todoListRepo: TodoListRepository,
) {}
}
```

We're now ready to add in some routes for our todo requests. To call the CRUD
methods on a todo-list's todo items, we'll first need to create a constrained
`TodoRepository`. We can achieve this by using our repository instance's `todos`
factory function that we defined earlier in `TodoListRepository`.

The `POST` request from `/todo-lists/{id}/todos` should look similar to the
following request:

{% include code-caption.html content="src/controllers/todo-list-todo.controller.ts" %}
As `src/controllers/todo-todo-list.controller.ts` only contains one method, we
can move it to the `Todo` controller and delete that file:

```ts
import {repository} from '@loopback/repository';
import {TodoListRepository} from '../repositories';
import {post, param, requestBody} from '@loopback/rest';
import {Todo} from '../models';

export class TodoListTodoController {
constructor(
@repository(TodoListRepository) protected todoListRepo: TodoListRepository,
) {}

@post('/todo-lists/{id}/todos')
async create(
@param.path.number('id') id: number,
@requestBody({
content: {
'application/json': {
schema: getModelSchemaRef(Todo, {title: 'NewTodo', exclude: ['id']}),
},
},
})
todo: Omit<Todo, 'id'>,
) {
return this.todoListRepo.todos(id).create(todo);
}
}
```
export class TodoController {
constructor() // ...
{}

Using our constraining factory as we did with the `POST` request, we'll define
the controller methods for the rest of the HTTP verbs for the route. The
completed controller should look as follows:
// other controller methods

{% include code-caption.html content="src/controllers/todo-list-todo.controller.ts" %}

```ts
import {
Count,
CountSchema,
Filter,
repository,
Where,
} from '@loopback/repository';
import {
del,
get,
getModelSchemaRef,
getWhereSchemaFor,
param,
patch,
post,
requestBody,
} from '@loopback/rest';
import {Todo} from '../models';
import {TodoListRepository} from '../repositories';

export class TodoListTodoController {
constructor(
@repository(TodoListRepository) protected todoListRepo: TodoListRepository,
) {}

@post('/todo-lists/{id}/todos', {
@get('/todos/{id}/todo-list', {
responses: {
'200': {
description: 'TodoList.Todo model instance',
content: {'application/json': {schema: getModelSchemaRef(Todo)}},
},
},
})
async create(
@param.path.number('id') id: number,
@requestBody({
content: {
'application/json': {
schema: getModelSchemaRef(Todo, {title: 'NewTodo', exclude: ['id']}),
},
},
})
todo: Omit<Todo, 'id'>,
): Promise<Todo> {
return this.todoListRepo.todos(id).create(todo);
}

@get('/todo-lists/{id}/todos', {
responses: {
'200': {
description: "Array of Todo's belonging to TodoList",
description: 'TodoList belonging to Todo',
content: {
'application/json': {
schema: {type: 'array', items: getModelSchemaRef(Todo)},
schema: {type: 'array', items: getModelSchemaRef(TodoList)},
},
},
},
},
})
async find(
@param.path.number('id') id: number,
@param.query.object('filter') filter?: Filter<Todo>,
): Promise<Todo[]> {
return this.todoListRepo.todos(id).find(filter);
}

@patch('/todo-lists/{id}/todos', {
responses: {
'200': {
description: 'TodoList.Todo PATCH success count',
content: {'application/json': {schema: CountSchema}},
},
},
})
async patch(
@param.path.number('id') id: number,
@requestBody({
content: {
'application/json': {
schema: getModelSchemaRef(Todo, {partial: true}),
},
},
})
todo: Partial<Todo>
@param.query.object('where', getWhereSchemaFor(Todo)) where?: Where<Todo>,
): Promise<Count> {
return this.todoListRepo.todos(id).patch(todo, where);
}

@del('/todo-lists/{id}/todos', {
responses: {
'200': {
description: 'TodoList.Todo DELETE success count',
content: {'application/json': {schema: CountSchema}},
},
},
})
async delete(
@param.path.number('id') id: number,
@param.query.object('where', getWhereSchemaFor(Todo)) where?: Where<Todo>,
): Promise<Count> {
return this.todoListRepo.todos(id).delete(where);
async getTodoList(
@param.path.number('id') id: typeof Todo.prototype.id,
): Promise<TodoList> {
return this.todoRepository.todoList(id);
}
}
```

Check out our `TodoList` example to see the full source code generated for the
`TodoListTodo` controller:
[src/controllers/todo-list-todo.controller.ts](https://github.com/strongloop/loopback-next/blob/master/examples/todo-list/src/controllers/todo-list-todo.controller.ts)

### Try it out

With the controllers complete, your application is ready to start up again!
Expand All @@ -333,4 +185,4 @@ And there you have it! You now have the power to define APIs for related models!

### Navigation

Previous step: [Add TodoList repository](todo-list-tutorial-repository.md)
Previous step: [Add Model Relations](todo-list-tutorial-relations.md)
Loading

0 comments on commit 91bd544

Please sign in to comment.