Hello, would someone be kind enough to show the function / hook method to update the name of an array based on the selected option in the array before saving. I have been going around in circles for two days, example code attached, - greatly appreciated.
{
name: 'theNameOfCertificate',
label: 'Add Certificate',
type: 'array',
fields: [
{
name: 'addCertificate',
type: 'select',
label: 'Select Certificate',
required: true,
options: [
{label: 'Drivers Licence', value: 'driversLicence',},
{label: 'Car Insurance', value: 'car_insurance',},
],
},
{
name: 'certificateImage',
type: 'upload',
label: 'Upload an image of your qualification',
unique: true,
relationTo: 'media',
required: true,
}
],
},
@CAPTKEN do you want to update the 'name' property on the array field? Maybe a different field would be better to update, for instance a text field, as the name is an identifier for the field and changing it dynamically will make it harder to query
like a certificateName field that is a string, and you set the value based on the selection of the select field
That way your addCertificate field isn't modified directly
@thisisnotchris thanks for your input, I had not thought of that, good point on searchability but these docs are in a users personal profile. Please see the screen shot attached which outlines the problem - the records are incremented by 01 and the user does not know which document is in the record ( the only way to find your drivers license is start opening every record until you get lucky ). Maybe their is another way of doing this if anyone knows - can a hook can be used or validateBefore function ? sorry but I do not have the smarts to work this out and chatgpt is dream up crazy answers so any help is greatly appreciated, as I am sure this question is bound to be raised again in the future.🙏
@CAPTKEN you are looking for “RowLabel” see the bottom of this docs page for an example:
https://payloadcms.com/docs/fields/array#config
You could add a name field inside the array as well, and then use that as the label. Or combine it with the type, or only use the type as a fallback. Plenty of ways to do what you are looking for 🙂
@Jarrod Thanks so much, learning as I go and will post results for others to follow
For those people that get stuck - this example code will help:
{
name: 'slider',
type: 'array',
label: 'Image Slider',
fields: [
{
name: 'Fruit',
type: 'select',
options: [
{label: "Apple", value: "apple"},
{label: "Pair", value: "pair"},
],
},
{
name: 'title',
type: 'text',
label: 'Title'
},
{
name: 'image',
type: 'upload',
label: 'Image',
relationTo: 'media',
required: true
},
],
admin: {
components: {
RowLabel: ({ data, index }) => {
const label = data?.title ? data.title :
Slide
;
return
${label} ${String(index + 1).padStart(2, '0')}
;
}
}
}
}
if you want to update the tile from the select option then replace the admin section with this code:
admin: {
components: {
RowLabel: ({ data, index }) => {
const label = data.fruit ? data.fruit:
Slide
;
return
${label} ${String(index + 1).padStart(2, '0')}
;
}
}
}
Thanks to @thisisnotchris and @Jarrod for your help 👋
Happy to help!
@thisisnotchris or @Jarrod I found that the above line in the admin section "const label = data.fruit ? data.fruit: Slide;" returns the value and not the label of the selected option- so fields in the array are renamed for example "apple_crumble_desert" rather then "Apple Crumble Desert". I have tried retrieving the label from that data using "const label = data.fruit.label ? data.fruit.label: Slide; " but it returns "unknown. Can you point me in the right direction please and thanks for your help guys.
You won't be able to get the label, just the value. However, you could think about this differently and move your options out of the select, turn them into a const variable, and then use that to determine what label to show in your row label
@Jarrod thanks for the pointer - Sorry I am still learning and only understanding the basics of what your saying - any chance you could share a code snippet that I can expand on and document in this post for others as well?
const fruits = {
apple: 'Apple',
pair: 'Pair',
}
const fruitOptions = Object.keys(fruits).map((key) => ({
value: key,
label: fruits[key],
}));
{
name: 'slider',
type: 'array',
label: 'Image Slider',
fields: [
{
name: 'Fruit',
type: 'select',
options: fruitOptions,
},
{
name: 'title',
type: 'text',
label: 'Title'
},
{
name: 'image',
type: 'upload',
label: 'Image',
relationTo: 'media',
required: true
},
],
admin: {
components: {
RowLabel: ({ data, index }) => {
const label = data.fruit ? fruits[data.fruit] : Slide;
return ${label} ${String(index + 1).padStart(2, '0')};
}
}
}
}
@Jarrod many thanks once again - would not of got this far with out your help - the complete code is below for others to follow
import { CollectionConfig, FieldHook } from 'payload/types';
const fruits = {
apple: 'Apple',
pear: 'Pear',
};
const fruitOptions = Object.keys(fruits).map((key) => ({
value: key,
label: fruits[key],
}));
const Test: CollectionConfig = {
slug: 'test',
fields: [
{
name: 'fruitshop',
type: 'array',
label: 'Image Slider',
fields: [
{
name: 'fruit',
type: 'select',
options: fruitOptions,
},
{
name: 'title',
type: 'text',
label: 'Title'
},
{
name: 'image',
type: 'upload',
label: 'Image',
relationTo: 'media',
required: true
},
],
admin: {
components: {
RowLabel: ({ data, index }) => {
const label = data.fruit ? fruits[data.fruit] : "Fruits";
return
${label} ${String(index + 1).padStart(2, '0')}
;
}
}
}
}
],
};
export default Test;
absolutely! happy to help 🙂
Star
Discord
online
Get help straight from the Payload team with an Enterprise License.