payload icon indicating copy to clipboard operation
payload copied to clipboard

chore(beta): pass req to defaultValue function and better type for defaultValue

Open r1tsuu opened this issue 10 months ago • 10 comments

Description

Currently defaultValue function argument is called only server side, so why pass only locale and user? It shouldn't be a breaking change because req contains them. You also can't use the Local API in defaultValue because of that,. Improved type for defaultValue, should respect all non-function values and function that accepts PayloadRequest.

  • [x] I have read and understand the CONTRIBUTING.md document in this repository.

Type of change

  • [x] Chore (non-breaking change which does not add functionality)
  • [x] This change requires a documentation update

Checklist:

  • [x] Existing test suite passes locally with my changes
  • [x] I have made corresponding changes to the documentation

r1tsuu avatar Apr 18 '24 18:04 r1tsuu

I love the idea of passing req to defaultValue. My only concern is that adding anything in the future, outside of req will get awkward. You would then need additional args or a breaking change to nest req into an object.

I'm considering it may make sense to keep { user, locale } and add req inside.

Maybe passing req is all we will ever need though, I can't think of a scenario that this is the case currently and adding to req is always possible in the future.

DanRibbens avatar Apr 19 '24 18:04 DanRibbens

I love the idea of passing req to defaultValue. My only concern is that adding anything in the future, outside of req will get awkward. You would then need additional args or a breaking change to nest req into an object.

I'm considering it may make sense to keep { user, locale } and add req inside.

Maybe passing req is all we will ever need though, I can't think of a scenario that this is the case currently and adding to req is always possible in the future.

I thought about that but then you would have data duplication in the argument object, it's not like a big deal but even in for example Access where we are using user object pretty much every time it's still in the req But i'm open to it

r1tsuu avatar Apr 19 '24 20:04 r1tsuu

@DanRibbens I have a group meta field used in multiple places. I want to have the defaultValue of a checkbox inside it be true on certain collections and false on others. Is it possible to access collection in addition to req so I can do something like this:

defaultValue: ({req, collection}) => {
	return collection.slug === "target-slug";
}

Unless you have a better suggestion.

todor0v avatar Apr 26 '24 10:04 todor0v

@DanRibbens I have a group meta field used in multiple places. I want to have the defaultValue of a checkbox inside it be true on certain collections and false on others. Is it possible to access collection in addition to req so I can do something like this:

defaultValue: ({req, collection}) => {
	return collection.slug === "target-slug";
}

Unless you have a better suggestion.

i think that shouldn't be specfic to defaultValue but rather your own implementation on how are you reusing the group field? you can always do this

import type { Field } from 'payload/types';
import type { Config } from 'payload-types';

const numberField = (collection: keyof Config['collections']): Field => {
  return {
    defaultValue: (req) => {
      switch (collection) {
        case 'admins':
          return 3;
        case 'posts':
          return 4;
      }

      return 5;
    },
    name: 'someNumber',
    type: 'number',
  };
};

Then in your collection config:

export const Collection: CollectionConfig = {
  fields: [numberField('admins')],
  slug: 'admins',
};

am i wrong about this?

you don't even need to have defaultValue as function here actually. you can do something like this

// in func
let defaultValue: number = 5;

switch (collection) {
 case "admins":
   defaultValue = 4;
}

return {
  type: "number",
  defaultValue,
  name: "someNumber"
|

r1tsuu avatar Apr 26 '24 10:04 r1tsuu

@r1tsuu Thank you for the suggestion! This would work, but I have to make a lot of changes to take advantage of it. I have a reusable meta field and I don't want to manually pass the collection I use it in. It is basically this:

export const metaField: Field = {
        name: "meta",
	type: "group",
        ....
        numberField('admins')
}

If I provide a parameter to numberField, I have to convert metaField to be a function and not just a field and receive this parameter anywhere it has been used just to cover this one case. If it is somehow possible to use defaultValue it seems much cleaner to me since that is what it should be responsible for anyway.

todor0v avatar Apr 26 '24 11:04 todor0v

I agree with @r1tsuu. This is on the side of your config code and payload doesn't pass the collection config to itself like that. It is better that we don't introduce circular references.

Because you already have a reused field it should be quick to find and replace it or change symbol in your IDE.

DanRibbens avatar Apr 26 '24 11:04 DanRibbens

Is it also possible to pass the search params? I need the id of a parent document as the default value for a drawer document (e.g. set a customer id as default value inside an order).

tobiasiv avatar May 03 '24 15:05 tobiasiv

Is it also possible to pass the search params? I need the id of a parent document as the default value for a drawer document (e.g. set a customer id as default value inside an order).

This PR solves that as req object contains searchParams. @DanRibbens what should i do? i can make it to keep user, locale and just pass req as you proposed.

r1tsuu avatar May 03 '24 15:05 r1tsuu

@r1tsuu @DanRibbens Do you guys have a status on this? I currently have a case where I need 'req' to be part of defaultValue.

mykz avatar Sep 17 '24 09:09 mykz