This article is a continuation of the following content: File structure part 2/6
The idea of the todo plugin is to have a list of tasks for every entry that you'll create in your project. This can be very useful for content-manager who wants to keep a clear vision of what needs to be done for a unique entry.
Todo is a simple list of tasks that needs to be saved in your application. Also, each task will be related to an existing entry but will see this later in this guide.
You can create a new collection-type using the generate
CLI command or by directly creating/updating the necessary files in your code editor. Here, we'll do both:
# yarn
yarn strapi generate content-type
# npm
npm run strapi generate content-type
1$ strapi generate content-type
2? Content type display name: Task
3? Content type singular name: task
4? Content type plural name: tasks
5? Please choose the model type: Collection Type
6? Use draft and publish? No
7? Do you want to add attributes? Yes
8? Name of attribute: name
9? What type of attribute: string
10? Do you want to add another attribute? Yes
11? Name of attribute: isDone
12? What type of attribute: boolean
13? Do you want to add another attribute? No
14? Where do you want to add this model? Add model to an existing plugin
15? Which plugin is this for? todo
16? Bootstrap API related files? No
The most important thing here is the ./src/plugins/todo/server/content-types/task/schema.json
. This is the schema of your plugin collection-type. We are going to customize it by opening it in a code editor:
1// ./src/plugins/todo/server/content-types/task/schema.json
2{
3 "kind": "collectionType",
4 "collectionName": "tasks",
5 "info": {
6 "singularName": "task",
7 "pluralName": "tasks",
8 "displayName": "Task"
9 },
10 "options": {
11 "draftAndPublish": false,
12 "comment": ""
13 },
14 "attributes": {
15 "name": {
16 "type": "string"
17 },
18 "isDone": {
19 "type": "boolean"
20 }
21 }
22}
To become the following:
1// ./src/plugins/todo/server/content-types/task/schema.json
2{
3 "kind": "collectionType",
4 "collectionName": "tasks",
5 "info": {
6 "singularName": "task",
7 "pluralName": "tasks",
8 "displayName": "Task"
9 },
10 "options": {
11 "draftAndPublish": false,
12 "comment": ""
13 },
14 "attributes": {
15 "name": {
16 "type": "string",
17 "required": true,
18 "maxLength": 40
19 },
20 "isDone": {
21 "type": "boolean",
22 "default": false
23 }
24 }
25}
As you can see, we are making the name
field required and it can only contain less than 40 characters. Also, the isDone
field is now false by default.
However, something is missing for Strapi to use this new collection-type. You need to make some manual updates.
Caution: These manual updates are necessary because of a bug in the generate CLI command. This will not be necessary for the future. The bug is that the schema created by Strapi is not automatically exported as it should be.
./src/plugins/todo/server/content-types/task/index.js
file that will export the schema generated by Strapi:1// ./src/plugins/todo/server/content-types/task/index.js
2'use strict';
3
4const schema = require('./schema');
5
6module.exports = {
7 schema,
8};
./src/plugins/todo/server/content-types/index.js
file by exporting the content-type you just created:1// ./src/plugins/todo/server/content-types/index.js
2'use strict';
3
4const task = require('./task');
5
6module.exports = {
7 task,
8};
You should now be able to see your new collection-type in the Content-Type Builder and Content Manager of your project.
Tipi: Don't forget, to build your admin to see your changes or follow this guide while having your server running with the --watch-admin
option.
You can verify the integrity of your collection-type by running your server and eval commands in your application in real-time using the strapi console
command.
# yarn
yarn strapi console
#npm
npm run strapi console
1strapi.contentType('plugin::todo.task')
You should see this:
1{
2 "kind": "collectionType",
3 "collectionName": "tasks",
4 "info": { "singularName": "task", "pluralName": "tasks", "displayName": "Task" },
5 "options": { "draftAndPublish": false, "comment": "" },
6 "attributes": {
7 "name": { "type": "string", "required": true, "maxLength": 40 },
8 "isDone": { "type": "boolean", "default": false },
9 "createdAt": { "type": "datetime" },
10 "updatedAt": { "type": "datetime" },
11 "createdBy": {
12 "type": "relation",
13 "relation": "oneToOne",
14 "target": "admin::user",
15 "configurable": false,
16 "writable": false,
17 "visible": false,
18 "useJoinTable": false,
19 "private": true
20 },
21 "updatedBy": {
22 "type": "relation",
23 "relation": "oneToOne",
24 "target": "admin::user",
25 "configurable": false,
26 "writable": false,
27 "visible": false,
28 "useJoinTable": false,
29 "private": true
30 }
31 },
32 "__schema__": {
33 "collectionName": "tasks",
34 "info": { "singularName": "task", "pluralName": "tasks", "displayName": "Task" },
35 "options": { "draftAndPublish": false, "comment": "" },
36 "attributes": { "name": [Object], "isDone": [Object] },
37 "kind": "collectionType"
38 },
39 "modelType": "contentType",
40 "modelName": "task",
41 "connection": "default",
42 "uid": "plugin::todo.task",
43 "plugin": "todo",
44 "globalId": "TodoTask",
45 "actions": undefined,
46 "lifecycles": undefined
47}
Next article: Server customization part 4/6
Maxime started to code in 2015 and quickly joined the Growth team of Strapi. He particularly likes to create useful content for the awesome Strapi community. Send him a meme on Twitter to make his day: @MaxCastres