Skip to content
KeystoneJS LogoKeystoneJSv5

Creating Relationships Between Lists

This chapter assumes that that the reader has the code that was created in Setup - Chapter 1 and Setup - Chapter 2.

Pick assignee from Users collection (to-single relationship)

Let's link the Todo list and the User list together by setting up a relationship. Tweak the assignee field in Todos.js to match the following code:

Import the Relationship field:

const { Text, CalendarDay, Checkbox, Relationship } = require('@keystonejs/fields');

Old code:

assignee: {
    type: Text,
    isRequired: true,
},

New code:

assignee: {
    type: Relationship,
    ref: 'User',
    isRequired: true,
},

The ref option defines the collection to which we will relate. The name assigned to the option is the same name that is passed to createList. In the AdminUI you can now pick one of the created users to make them responsible for completing the task.

Pick task from Todos collection (two-way to-single relationship)

Is is now possible to assign a task to a user, but it is not possible to assign the user to a task! Let's fix this. In Users.js add the following:

module.exports = {
  // ...
  task: {
    type: Relationship,
    ref: 'Todo',
  },
};

Now we can set a task for the User from the admin panel. But something is wrong! When we pick a task for the user and then check this task, the assignee is incorrect. This can be solved by using a Back Reference.

Enabling Back Reference between Users and Todos

Back Reference is KeystoneJS' mechanism that can overwrite fields of the referenced entity. It is better seen in action, so let's write some code first.

In Users.js adjust the task field to the following:

task: {
    type: Relationship,
    ref: 'Todo.assignee',
}

And in Todos.js update the assignee field:

assignee: {
    type: Relationship,
    ref: 'User.task',
}

Start the AdminUI and create a Todo and assign a user. Check the user's task field and notice that it is already set! When a user is created and a Todo is assigned, the assignee field won't be filled in. Add the following code to make it work both ways:

task: {
    type: Relationship,
    ref: 'Todo.assignee',
}

To test it out, remove the isRequired: true property from the assignee field in the Todos file:

assignee: {
    type: Relationship,
    ref: 'User.task',
    // isRequired: true,
},

Create a Todo without assigning it to a user. Then go to a user, assign a Todo to the task field. Go back to the todo and notice that the assignee field has been filled in.

Assigning multiple tasks to a user (to-many relationship)

What if a user needs to be able to do multiple tasks? KeystoneJS provides a way to do this easily. Take a look at following code in Users.js:

tasks: {
    type: Relationship,
    ref: 'Todo.assignee',
    many: true,
}

The many: true option indicates that User can store multiple references to tasks. Note that we've changed task to tasks. Copy this code to your application and don't forget to change the assignee field in Todos.js to match the new field name User.tasks. Now in the AdminUI you can pick multiple tasks for a user.

See also:

Have you found a mistake, something that is missing, or could be improved on this page? Please edit the Markdown file on GitHub and submit a PR with your changes.

Edit Page