I am struggling to calculate fields which would benefit from being worked out before submission. I can see there is useField
, siblingData
and useWatchForm
. I assume these are used in some fashion to achieve this.
I can't find any information on how to use math to automate some of the fields, but I assume that it's more than capable in PayloadCMS. I'm just getting to grips with js, react and typescript, so I'm not well versed in the correct syntax and structure of the code just yet, so just keep making spaghetti code and creating a tonne of errors and not getting anywhere very quickly.
How would I go about grabbing 2 or 3 numerical fields to then calculate to find the total?
This is an example of my code. I'm basically trying to do pretty simple maths, but I don't know where to pull my data from or how to calculate it. Can anyone give me some pointers?
import {
CollectionConfig,
} from 'payload/types';
const userHealthCheck: CollectionConfig = {
slug: 'userhealthcheck',
admin: {
defaultColumns: ['name', 'height', 'weight', 'hips', 'waist'],
useAsTitle: 'title',
},
access: {
read: () => true,
},
fields: [{
name: 'name',
type: 'text',
label: 'Name'
},
{
name: 'height',
type: 'number',
label: 'Height in cm'
},
{
name: 'weight',
type: 'number',
label: 'Weight in kg'
},
{
name: 'hips',
type: 'number',
label: 'Hips'
},
{
name: 'waist',
type: 'number',
label: 'Waist'
},
{
name: 'waisttohips_ratio',
type: 'number',
label: 'Waist to Hips Ratio'
//Calculate Waist / Hips = Waist Hips ratio
},
{
name: 'bmi',
type: 'number',
label: 'BMI',
//Calculate [weight (kg) / height (cm) / height (cm)] x 10,000
}
]
}
export default userHealthCheck;
Hi @GronsoBitburg,
That sounds like a good use for hooks.
import { CollectionBeforeChangeHook } from 'payload/types'
const healthCheckCalculations: CollectionBeforeChangeHook : CollectionBeforeChangeHook = ({data}) => {
data.bmi = data.weight / data.height / data.height * 10000;
data.waisttohips_ratio = data.waist / data.hips;
}
const userHealthCheck: CollectionConfig = {
slug: 'userhealthcheck',
hooks: {
beforeChange: [ healthCheckCalculations ],
},
// rest of the collection
}
By the way, that read access () => true means that everybody including guest users who have not logged in can query and read your data on this collection. I want to be sure you know that since it sounds like some personal information.
Just trying out your code and I'm getting two errors:
[{
"resource": "/gronso/health-payload-cms/src/collections/HealthCheck.ts",
"owner": "typescript",
"code": "2304",
"severity": 8,
"message": "Cannot find name 'BeforeChangeHook'.",
"source": "ts",
"startLineNumber": 1,
"startColumn": 32,
"endLineNumber": 1,
"endColumn": 48
}]
[{
"resource": "/gronso/health-payload-cms/src/collections/HealthCheck.ts",
"owner": "typescript",
"code": "1005",
"severity": 8,
"message": "',' expected.",
"source": "ts",
"startLineNumber": 1,
"startColumn": 48,
"endLineNumber": 1,
"endColumn": 49
}]
Somehow BeforeChangeHook
can't be found.
This is my code with your suggestion added, have I done something wrong?
const healthCheckCalculations: BeforeChangeHook: CollectionBeforeChangeHook = ({data}) => {
data.bmi = data.weight / data.height / data.height * 10000;
data.waisttohips_ratio = data.waist / data.hips;
}
import {
CollectionConfig, CollectionBeforeChangeHook
} from 'payload/types';
const userHealthCheck: CollectionConfig = {
slug: 'userhealthcheck',
hooks: {
beforeChange: [ healthCheckCalculations ]
},
admin: {
defaultColumns: ['name', 'height', 'weight', 'hips', 'waist'],
useAsTitle: 'title',
},
access: {
read: () => true,
},
fields: [{
name: 'name',
type: 'text',
label: 'Name'
},
{
name: 'height',
type: 'number',
label: 'Height in cm'
},
{
name: 'weight',
type: 'number',
label: 'Weight in kg'
},
{
name: 'hips',
type: 'number',
label: 'Hips'
},
{
name: 'waist',
type: 'number',
label: 'Waist'
},
{
name: 'waisttohips_ratio',
type: 'number',
label: 'Waist to Hips Ratio'
//Calculate Waist / Hips = Waist Hips ratio
},
{
name: 'bmi',
type: 'number',
label: 'BMI',
//Calculate [weight (kg) / height (cm) / height (cm)] x 10,000
}
]
}
export default userHealthCheck;
Check my answer for updated code. I didn't have the import at the top and BeforeChangeHook
was supposed to be CollectionBeforeChangeHook
. Sorry about the confusion.
I'm sorry for being a pain Dan.
I noticing that there was still an error occurring and I had no idea why.
After a bit of bumbling about with the code I realised that
const healthCheckCalculations : CollectionBeforeChangeHook : CollectionBeforeChangeHook = ({data}) => {
was throwing an error and that by deleting : CollectionBeforeChangeHook
to now be:
const healthCheckCalculations : CollectionBeforeChangeHook = ({data}) => {
This fixed the issue and now the code works flawlessly. Thank you so much for helping me.
Of course, sorry I was editing on mobile! Glad you worked it out.
Wait... It's that easy? I was really over complicating it
Thank you so much for taking the time to help. I was thinking that it was gonna be a lot more complicated to get that working.
The read access () => true is just so I can play around with payload as I'll have to figure out the api section (when I get to that bit). This project won't go any further than my intranet so I'm pretty comfortable with that. To be honest, I should have removed that for any new user reading my post.
Star
Discord
online
Get help straight from the Payload team with an Enterprise License.