Page Contents

We have that a Todo belongsTo a TodoList and a TodoList hasMany Todos. Another type of relation we can add is hasOne. To do so, let’s add TodoListImage such that each TodoList hasOne image. In parallel, a TodoListImage will belong to a TodoList, similar to how a Todo belongs to TodoList.

Create the Model

Similar to how we created the model for TodoList, using lb4 model:

lb4 model
? Model class name: TodoListImage
? Please select the model base class Entity (A persisted model with an ID)
? Allow additional (free-form) properties? No
Model TodoListImage will be created in src/models/todo-list-image.model.ts

Let's add a property to TodoListImage
Enter an empty property name when done

? Enter the property name: id
? Property type: number
? Is id the ID property? Yes
? Is id generated automatically? No
? Is it required?: No
? Default value [leave blank for none]:

Let's add another property to TodoListImage
Enter an empty property name when done

? Enter the property name: value
? Property type: string
? Is it required?: Yes
? Default value [leave blank for none]:

Let's add another property to TodoListImage
Enter an empty property name when done

? Enter the property name:
   create src/models/todo-list-image.model.ts
   update src/models/index.ts

Model TodoListImage was created in src/models/

Create the Repository

Using lb4 repository, let’s create the repository:

lb4 repository
? Please select the datasource DbDatasource
? Select the model(s) you want to generate a repository TodoListImage
? Please select the repository base class DefaultCrudRepository (Juggler bridge)
   create src/repositories/todo-list-image.repository.ts
   update src/repositories/index.ts

Repository TodoListImageRepository was created in src/repositories/

Create the Controller

Using lb4 controller, let’s create the controller:

$ lb4 controller
? Controller class name: TodoListImage
Controller TodoListImage will be created in src/controllers/todo-list-image.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? TodoListImage
? What is the name of your CRUD repository? TodoListImageRepository
? 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-list-images
   create src/controllers/todo-list-image.controller.ts
   update src/controllers/index.ts

Controller TodoListImage was created in src/controllers/

Add the Relation

Adding a hasOne relation is similar to the HasMany relation. Let’s use the lb4 relation command.

$ lb4 relation
? Please select the relation type hasOne
? Please select source model TodoList
? Please select target model TodoListImage
? Foreign key name to define on the target model todoListId
? Source property name for the relation getter (will be the relation name) image
? Allow TodoList queries to include data from related TodoListImage instances? Yes
   create src/controllers/todo-list-todo-list-image.controller.ts

Relation HasMany was created in src/

Now, we’re going to add the relation for TodoListImage. That is, TodoListImage belongsTo TodoList:

$ lb4 relation
? Please select the relation type belongsTo
? Please select source model TodoListImage
? Please select target model TodoList
? Foreign key name to define on the source model todoListId
? Relation name todoList
? Allow TodoListImage queries to include data from related TodoList instances? Yes
   create src/controllers/todo-list-image-todo-list.controller.ts

Relation BelongsTo was created in src/

As you can see, this created the relational controllers todo-list-todo-list-image.controller.ts and todo-list-image-todo-list.controller.ts.

As src/controllers/todo-list-image-todo-list.controller.ts only contains one method, we can move it to the TodoListImage controller and delete that file:

src/controllers/todo-list-image.controller.ts

import {repository} from '@loopback/repository';
import {param, get, getModelSchemaRef} from '@loopback/rest';
import {TodoListImage, TodoList} from '../models';
import {TodoListImageRepository} from '../repositories';

export class TodoListImageController {
  constructor() {} // ...

  // other controller methods
  @get('/todo-list-images/{id}/todo-list', {
    responses: {
      '200': {
        description: 'TodoList belonging to TodoListImage',
        content: {
          'application/json': {
            schema: {type: 'array', items: getModelSchemaRef(TodoList)},
          },
        },
      },
    },
  })
  async getTodoList(
    @param.path.number('id') id: typeof TodoListImage.prototype.id,
  ): Promise<TodoList> {
    return this.todoListImageRepository.todoList(id);
  }
}

Then you should see the new added property image is decorated with the decorator @hasOne in the TodoList to represent the TodoListImage this TodoList has:

src/models/todo-list.model.ts

import {hasOne} from '@loopback/repository';
import {
  TodoListImage,
  TodoListImageWithRelations,
} from './todo-list-image.model';

@model()
export class TodoList extends Entity {
  // ... other properties

  @hasOne(() => TodoListImage)
  image: TodoListImage;

  // ...
}

export interface TodoListRelations {
  todos?: TodoWithRelations[];

  // Add the following line
  image?: TodoListImageWithRelations;
}

If you check the TodoListImage model, you will find that the foreign key todoListId is being added and decorated with @belongsTo:

src/models/todo-list-image.model.ts

import {belongsTo} from '@loopback/repository';
import {TodoList, TodoListWithRelations} from './todo-list.model';

@model()
export class TodoListImage extends Entity {
  // ... other properties

  @belongsTo(() => TodoList)
  todoListId: number;

  // ...
}

export interface TodoListImageRelations {
  todoList?: TodoListWithRelations;
}

Try to create instances and traverse the data as what we showed in the previous step yourself!

Previous step: Add TodoList Relations

Last step: Add TodoList Controller