Here is my data structure :
{
name: "userPlannerTasks",
type: "group",
fields: [
{
name: "daily",
label: "Every day",
type: "array",
fields: [
{
name: "title",
label: "Title",
type: "text",
required: true,
},
{
name: "frequency",
label: "Frequency",
type: "text",
required: true,
},
{
name: "index",
label: "Index",
type: "number",
required: true,
},
{
name: "startingTime",
label: "Starting time",
type: "text",
required: false,
},
{
name: "endingTime",
label: "Ending time",
type: "text",
required: false,
},
{
name: "completedAt",
label: "Completion time",
type: "date",
required: false,
},
],
{
name: "weekly",
label: "Every week",
type: "array",
fields: [same as daily]
},
My use case goes like this :
- I have a front-end that display daily tasks.
- A user can have many daily tasks.
- When a user completes a task, he can check it to mark it completed.
My goal is to update in the array of daily tasks the right object according to the index of the daily task shown in the front-end (FE). E.G : If my task checked in the FE is the second one in the list, I want to update the document at index 1.
From what I understand I could simply send the whole array of daily tasks with a patch request through
/my_slug/documentId
.
Although I don't know if it's possible to target an object in a array through Payload's REST API or I have to use the hooks?
Thank you 🙂
You see an id has been added to each object in the array. If you send only the object you want to modify with the id in the patch it will update just that one. None of the other objects in the array should be affected.
Following my structure of the object I managed to achieve what I wanted to do through a "PATCH" request. Much appreciated for your help @dribbens
!
Mhmm... for some reason it doesn't seem to work. Here's my current document :
{
"_id": {
"$oid": "64dae4b246f3b71b7c8b8af2"
},
"user": "a_user_id",
"userPlannerTasks": {
"daily": [
{
"title": "Make your bed",
"frequency": "daily",
"index": 0,
"id": "74b70c73-c31c-485f-b12c-bd84a4cf5cbb"
},
{
"title": "Make your bed",
"frequency": "daily",
"index": 1,
"id": "ce3a56d4-e714-4e80-a6bc-5b408061aeb7"
}
],
"weekly": [],
"monthly": [],
"yearly": []
},
"updatedAt": {
"$date": "2023-08-16T04:43:21.902Z"
}
}
And here is my payload :
{
"userPlannerTasks":
{
"daily":[
{
"id": "74b70c73-c31c-485f-b12c-bd84a4cf5cbb",
"completedAt": "2024-08-15T04:22:05.913Z"
}
]
}
}
Here is my query :
{{api-link}}/user_planner_tasks/64dae4b246f3b71b7c8b8af2
. It's a
PATCHrequest
According to your input, it should only update the first task of making your bed. It seems to patch the current document with the current payload therefore erasing the second instance of
Making your bed
The id for each task is generated through the front-end application with uuidv4(). I don't know if it has an impact.
Oh my bad. If you can pass through the rest of the task IDs they won't get removed. Are you dealing with a large number of items in the array? What is the reason you don't want to do that?
You could add a custom endpoint that gets the document and only updates the one item in the array matching the id found instead of changing them all.
Another alternative would be to add a hidden group field with the same subfields as your array. Using a before change hook you are going to find and set the item in your array by the uuid, leaving all the others the same and not returning your virtual group value so that it isn't persisted.
Thanks @dribbens for your answer
Yep exactly I could end up having hundred of items being sent because of one simple modification. Lets say I have 100 daily tasks and I want to complete the second task only. I would need to send the data of the 99 other tasks also.
My initial take was to go with custom end points but while playing with them I figured out that the access control don't apply to custom endpoints?
Also I'm not really understanding what do you mean by adding a hidden group field?
A custom endpoint is probably easier than the hidden group idea for updating an item in the array.
You can use access control all the same by passing the
req
through to payload.update(). It will provide the same validation and access control as if you were hitting the endpoint directly.
Just curious...wouldn't it be easier to just create a separate collection for your tasks and map them as a relationship to a task list?
@dribbens Yep I ended up doing a custom endpoint. I really wanted to stick with Payload's REST API.
@superwafflepuffs My initial approach was to map them as a relationship but I can't remember why it didn't work. Now that I think of it, doing so would allow me to update a single task as intended...
Ye, also just thinking of other good reasons for a TaskCollection { listId } type setup would be if you wanted to move tasks between lists that would be really easy. cloning tasks as well.
Star
Discord
online
Get help straight from the Payload team with an Enterprise License.