Collection config allow me to overwrite payload ID implement, but can't define defaultValue. Classic ID numbering is not an option to me, to prevent users discovering and playing with other entries, just changing ID.
Would like to fully customize using nanoID but any ID like, its totally fine. Is it possible?
Hey @didiraja,
I was surprised that defaultValue is not allowed for custom ID fields. As another workaround you could add it to the beforeValidate hook like this:
// in your collection:
hooks: {
beforeValidate: [({ data }) => {
if (!data.id) {
// replace with your own way to generate IDs
const customID = uuid()
return {...data, id: customID }
}
return data
}],
},
fields: [
{
name: 'id',
type: 'text',
admin: {
components: {
Field: () => null,
},
},
},
// ... rest of the fields
}]
@didiraja please mark this as answered if it solved your issue. If not, I'm curious what happened.
Thanks!
@DanRibbens worked flawlessly, thanks!
We should take into account that storing UUIDs as strings in the databases leads to significantly decreased performance of the findByID, where conditions, and join queries! The most performant way is to store the UUID in binary format, which will use 16 bytes instead of 32-36 bytes compared to string format.
But seems it is not possible for now in the Payload, because it requires configuring the MongoDB (or SQL) adapter to automatically convert the value to the binary format.
So, I created an appeal to use UUID by default in the Payload CMS: #15548
This is an addition to the feature request to allow using different ids #13054
And a draft PR that implements UUID support for the MongoDB adapter: #15522
Let's join forces and make Payload CMS better together! 😉
@DanRibbens This is how Payload reacts when I try to overwrite id object using defaultValue:
collection definition:
const Events: CollectionConfig = {
slug: 'events',
auth: false,
admin: {
useAsTitle: 'title',
},
fields: [
{
name: 'id',
type: 'text',
defaultValue: nanoid(),
required: true,
},
{
label: 'Título',
name: 'title',
type: 'text',
required: true,
},
terminal output:
[nodemon] 2.0.22
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: ts
[nodemon] starting `ts-node src/server.ts -- -I`
[12:12:19] ERROR (payload): There were 1 errors validating your Payload config
[12:12:19] ERROR (payload): 1: Collection "events" > Field "id" > "defaultValue" is not allowed
[nodemon] app crashed - waiting for file changes before starting..
defaultValue kind of works in payload v3.
fields: [
{
name: 'id',
type: 'text',
required: true,
defaultValue: uuid,
hidden: true
}]
If we keep the id hidden, it works on create page.
But on list page all entries get the same id.
It generates a new uuid which not does match any entry and clicking on any entry takes you to 404.
Following works as fix.
fields: [
{
name: 'id',
type: 'text',
required: true,
defaultValue: uuid,
admin: {
components: {
Field: undefined,
},
},
},Hm, if I do the above I get a MongooseError "document must have an _id before saving", what am I missing? Cheers
Interesting workaround for the issue with Field: undefined - could anyone describe why it works and why this doesn't work well by default, without this fix?
@didiraja @jashwant @DanRibbens @DracoBlue @mtcrutch
I created this plugin:
https://www.npmjs.com/package/payload-default-value-gen
hopes it will fit your needs :)
Hi, does providing custom id work for you when using relationship type from another collection towards the collection with generated text ID? I use postgres adapter and migrations payload generates create foreign key field with type number in the other collection, therefore failing to process foreign key constraint "xxx" cannot be implemented
Key columns \"referenced_id\" and \"id\" are of incompatible types: integer and character varying.",
oh i solved my problemy myself - the fix was to set idType: 'uuid', in pg adapter settings
@bgulowaty Happy to hear, thanks for sharing!
Star
Discord
online
Get dedicated engineering support directly from the Payload team.