Skip to content

Commit 306d437

Browse files
shimksdhmlau
authored andcommitted
feat(example-todo-list): add TodoList package/tutorial
1 parent fa33520 commit 306d437

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+2202
-22
lines changed

docs/site/Examples-and-tutorials.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ LoopBack 4 comes with the following example projects:
1616
- **[todo](todo-tutorial.md)**: Tutorial on building a simple application with
1717
LoopBack 4 key concepts using bottom-up approach.
1818

19+
- **[todo-list](todo-list-tutorial.md)**: Tutorial on introducing related models
20+
and building their API from the Todo tutorial
21+
1922
- **[log-extension](https://github.com/strongloop/loopback-next/tree/master/examples/log-extension)**:
2023
Tutorial on building a log extension.
2124

@@ -25,11 +28,12 @@ LoopBack 4 comes with the following example projects:
2528
You can download any of the example projects usig our CLI tool `lb4`:
2629

2730
```sh
28-
lb4 example
31+
$ lb4 example
2932
? What example would you like to clone? (Use arrow keys)
30-
❯ todo: Tutorial example on how to build an application with LoopBack 4.
31-
hello-world: A simple hello-world Application using LoopBack 4
32-
log-extension: An example extension project for LoopBack 4
33+
> todo: Tutorial example on how to build an application with LoopBack 4.
34+
todo-list: Continuation of the todo example using relations in LoopBack 4.
35+
hello-world: A simple hello-world Application using LoopBack 4.
36+
log-extension: An example extension project for LoopBack 4.
3337
rpc-server: A basic RPC server using a made-up protocol.
3438
```
3539

docs/site/sidebars/lb4_sidebar.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,23 @@ children:
5757
url: todo-tutorial-geocoding-service.html
5858
output: 'web, pdf'
5959

60+
- title: 'TodoList Tutorial'
61+
url: todo-list-tutorial.html
62+
output: 'web, pdf'
63+
children:
64+
65+
- title: 'Add TodoList Model'
66+
url: todo-list-tutorial-model.html
67+
output: 'web, pdf'
68+
69+
- title: 'Add TodoList Repository'
70+
url: todo-list-tutorial-repository.html
71+
output: 'web, pdf'
72+
73+
- title: 'Add TodoList Controller'
74+
url: todo-list-tutorial-controller.html
75+
output: 'web, pdf'
76+
6077
- title: 'Key concepts'
6178
url: Concepts.html
6279
output: 'web, pdf'
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
---
2+
lang: en
3+
title: "Add TodoList and TodoList's Todo Controller"
4+
keywords: LoopBack 4.0, LoopBack 4
5+
tags:
6+
sidebar: lb4_sidebar
7+
permalink: /doc/en/lb4/todo-list-tutorial-controller.html
8+
summary: LoopBack 4 TodoList Application Tutorial - Add TodoList and TodoList's Todo Controller
9+
---
10+
11+
### Controllers with related models
12+
13+
Defining business logic to handle requests to related models isn't too different
14+
from handling requests for standalone models. We'll create controllers to handle
15+
requests for todo-lists and todo items under a todo-list.
16+
17+
### Create TodoList controller
18+
19+
Run the CLI command for creating a RESTful CRUD controller for our `TodoList`
20+
routes with the following inputs:
21+
22+
```sh
23+
$ lb4 controller
24+
? Controller class name: TodoList
25+
? What kind of controller would you like to generate? REST Controller with CRUD functions
26+
? What is the name of the model to use with this CRUD repository? TodoList
27+
? What is the name of your CRUD repository? TodoRepository
28+
? What is the type of your ID? number
29+
? What is the base HTTP path name of the CRUD operations? /todo-lists
30+
create src/controllers/todo-list.controller.ts
31+
update src/controllers/index.ts
32+
33+
Controller TodoList was created in src/controllers/
34+
```
35+
36+
And voilà! We now have a set of basic APIs for todo-lists just like that!
37+
38+
### Create TodoList's Todo controller
39+
40+
For the controller handling `Todos` of a `TodoList`, we'll start with an empty
41+
controller:
42+
43+
```sh
44+
$ lb4 controller
45+
? Controller class name: TodoListTodo
46+
? What kind of controller would you like to generate? Empty Controller
47+
create src/controllers/todo-list-todo.controller.ts
48+
update src/controllers/index.ts
49+
50+
Controller TodoListTodo was created in src/controllers/
51+
```
52+
53+
Let's add in an injection for our `TodoListRepository`:
54+
55+
#### src/controllers/todo-list-todo.controller.ts
56+
57+
```ts
58+
import {repository} from '@loopback/repository';
59+
import {TodoListRepository} from '../repositories';
60+
61+
export class TodoListTodoController {
62+
constructor(
63+
@repository(TodoListRepository) protected todoListRepo: TodoListRepository,
64+
) {}
65+
}
66+
```
67+
68+
With this, we're now ready to add in some routes for our todo requests. To call
69+
the CRUD methods on a todo-list's todo items, we'll first need to create a
70+
constrained `TodoRepository`. We can achieve this by using our repository
71+
instance's `todos` factory function that we defined earlier in
72+
`TodoListRepository`.
73+
74+
The `POST` request from `/todo-lists/{id}/todos` should look something like
75+
this:
76+
77+
#### src/controllers/todo-list-todo.controller.ts
78+
79+
```ts
80+
import {repository} from '@loopback/repository';
81+
import {TodoListRepository} from '../repositories';
82+
import {post, param, requestBody} from '@loopback/rest';
83+
import {Todo} from '../models';
84+
85+
export class TodoListTodoController {
86+
constructor(
87+
@repository(TodoListRepository) protected todoListRepo: TodoListRepository,
88+
) {}
89+
90+
@post('/todo-lists/{id}/todos')
91+
async create(@param.path.number('id') id: number, @requestBody() todo: Todo) {
92+
return await this.todoListRepo.todos(id).create(todo);
93+
}
94+
}
95+
```
96+
97+
Using our constraining factory as we did with the `POST` request, we'll define
98+
the controller methods for the rest of the HTTP verbs for the route. The
99+
completed controller should look as follows:
100+
101+
#### src/controllers/todo-list-todo.controller.ts
102+
103+
```ts
104+
import {repository, Filter, Where} from '@loopback/repository';
105+
import {TodoListRepository} from '../repositories';
106+
import {post, get, patch, del, param, requestBody} from '@loopback/rest';
107+
import {Todo} from '../models';
108+
109+
export class TodoListTodoController {
110+
constructor(
111+
@repository(TodoListRepository) protected todoListRepo: TodoListRepository,
112+
) {}
113+
114+
@post('/todo-lists/{id}/todos')
115+
async create(@param.path.number('id') id: number, @requestBody() todo: Todo) {
116+
return await this.todoListRepo.todos(id).create(todo);
117+
}
118+
119+
@get('/todo-lists/{id}/todos')
120+
async find(
121+
@param.path.number('id') id: number,
122+
@param.query.string('filter') filter?: Filter,
123+
) {
124+
return await this.todoListRepo.todos(id).find(filter);
125+
}
126+
127+
@patch('/todo-lists/{id}/todos')
128+
async patch(
129+
@param.path.number('id') id: number,
130+
@requestBody() todo: Partial<Todo>,
131+
@param.query.string('where') where?: Where,
132+
) {
133+
return await this.todoListRepo.todos(id).patch(todo, where);
134+
}
135+
136+
@del('/todo-lists/{id}/todos')
137+
async delete(
138+
@param.path.number('id') id: number,
139+
@param.query.string('where') where?: Where,
140+
) {
141+
return await this.todoListRepo.todos(id).delete(where);
142+
}
143+
}
144+
```
145+
146+
### Try it out
147+
148+
With the controllers complete, your application is ready to start up again!
149+
`@loopback/boot` should wire up everything for us when we start the application,
150+
so there's nothing else we need to do before we try out our new routes.
151+
152+
```sh
153+
$ npm start
154+
Server is running at http://127.0.0.1:3000
155+
```
156+
157+
Here are some new requests you can try out:
158+
159+
- `POST /todo-lists` with a body of `{ "title": "grocery list" }`.
160+
- `POST /todo-lists/{id}/todos` using the ID you got back from the previous
161+
`POST` request and a body for a todo. Notice that response body you get back
162+
contains property `todoListId` with the ID from before.
163+
- `GET /todos/{id}/todos` and see if you get the todo you created from before.
164+
165+
And there you have it! You now have the power to define API for related models!
166+
167+
### Navigation
168+
169+
Previous step: [Add TodoList repository](todo-list-tutorial-repository.md)

docs/site/todo-list-tutorial-model.md

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
---
2+
lang: en
3+
title: 'Add TodoList Model'
4+
keywords: LoopBack 4.0, LoopBack 4
5+
tags:
6+
sidebar: lb4_sidebar
7+
permalink: /doc/en/lb4/todo-list-tutorial-model.html
8+
summary: LoopBack 4 TodoList Application Tutorial - Add TodoList Model
9+
---
10+
11+
### Building a checklist for your Todo models
12+
13+
A todo item is often grouped into a checklist along with other todo items so
14+
that it can be used to measure the progress of a bigger picture that the item is
15+
a part of.
16+
17+
A set of data can often be related to another; an entity may be able to provide
18+
access to another based on its relationship with the other entity. To take
19+
`TodoListApplication` one step further and establish relations with the existing
20+
`Todo` model as real-world applications often tend to do, we'll introduce the
21+
model `TodoList`.
22+
23+
We'll create `TodoList` model to represent a checklist that contains multiple
24+
Todo items. Let's define TodoList model with the following properties:
25+
26+
- a unique id
27+
- a title
28+
- a color to represent the TodoList with
29+
30+
We can use the `lb4 model` command and answer the prompts to generate the model
31+
for us as follows:
32+
33+
```sh
34+
$ lb4 model
35+
? Model class name: TodoList
36+
37+
Let's add a property to TodoList
38+
Enter an empty property name when done
39+
40+
? Enter the property name: id
41+
? Property type: number
42+
? Is ID field? Yes
43+
? Required?: No
44+
? Default value [leave blank for none]:
45+
46+
Let's add another property to TodoList
47+
Enter an empty property name when done
48+
49+
? Enter the property name: title
50+
? Property type: string
51+
? Required?: Yes
52+
? Default value [leave blank for none]:
53+
54+
Let's add another property to TodoList
55+
Enter an empty property name when done
56+
57+
? Enter the property name: color
58+
? Property type: string
59+
? Required?: No
60+
? Default value [leave blank for none]:
61+
62+
Let's add another property to TodoList
63+
Enter an empty property name when done
64+
65+
? Enter the property name:
66+
create src/models/todo-list.model.ts
67+
update src/models/index.ts
68+
69+
Model TodoList was created in src/models/
70+
```
71+
72+
Now that we have our new model, it's time to define its relation with the `Todo`
73+
model. To `TodoList` model, add in the following property:
74+
75+
#### src/models/todo-list.model.ts
76+
77+
```ts
78+
@model()
79+
export class TodoList extends Entity {
80+
// ...properties defined by the CLI...
81+
82+
@hasMany(Todo) todos?: Todo[];
83+
84+
// ...constructor def...
85+
}
86+
```
87+
88+
Notice that `@hasMany()` decorator is used to define this property. As the
89+
decorator's name suggests, this will let LoopBack 4 know that a todo list can
90+
have many todo items.
91+
92+
To complement `TodoList`'s relationship to `Todo`, we'll add in `todoListId`
93+
property on `Todo` model to complete defining the relation on both ends:
94+
95+
### src/models/todo.model.ts
96+
97+
```ts
98+
@model()
99+
export class Todo extends Entity {
100+
// ...properties defined by the CLI...
101+
102+
@property() todoListId: number;
103+
104+
// ...constructor def...
105+
}
106+
```
107+
108+
Once the models have been completely configured, it's time to move on to adding
109+
a [repository](todo-list-tutorial-repository.md) for `TodoList`.
110+
111+
### Navigation
112+
113+
Introduction: [TodoList Tutorial](todo-list-tutorial.md)
114+
115+
Next step: [Add TodoList repository](todo-list-tutorial-repository.md)

0 commit comments

Comments
 (0)