Adding Calculations to Collection Form

default discord avatar
GronsoBitburg
last year
1 2

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;
  • discord user avatar
    DanRibbens
    Payload Team
    last year

    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.

    4 replies
  • default discord avatar
    GronsoBitburg
    last year

    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;
  • discord user avatar
    DanRibbens
    Payload Team
    last year

    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.

  • default discord avatar
    GronsoBitburg
    last year

    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.

  • discord user avatar
    DanRibbens
    Payload Team
    last year

    Of course, sorry I was editing on mobile! Glad you worked it out.

  • default discord avatar
    GronsoBitburg
    last year

    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.

Open the post
Continue the discussion in GitHub
Like what we're doing?
Star us on GitHub!

Star

Connect with the Payload Community on Discord

Discord

online

Can't find what you're looking for?

Get help straight from the Payload team with an Enterprise License.