Populate value to read only field

default discord avatar
jasonkw9
last year
1 2

I have a relation field which link to product collection and this product collection contains of the price of each product. What I am trying to achieve is to populate the price of the product to a read only field after the product is selected. I've attach a screenshot for better understanding.

Screenshot 2022-08-27 at 12 56 29 AM

  • discord user avatar
    DanRibbens
    Payload Team
    last year

    Hey @jasonkw9,

    I've done this before for a project where I need to calculate some field based on sibling data changes. To do it I used the useWatchForm hook to calculate the updates in a useEffect. Here is an example:

    const ProviderFee: React.FC<{ path: string }> = ({ path }) => {
      const { getDataByPath } = useWatchForm();
      const { value, setValue } = useField({ path });
    
      const type: string = getDataByPath('type');
      const amount: number = getDataByPath('amount');
      const feePercentage: number = getDataByPath('feePercentage');
    
      useEffect(() => {
        if (typeof amount === 'number' && typeof feePercentage === 'number') {
          setValue((feePercentage / 100) * Math.abs(amount));
        } else if (value !== 0 && value !== undefined) {
          setValue(0);
        }
      }, [value, type, amount, feePercentage, setValue]);
    
      return (
        <div>
          <span>
            <TextInput
              path="fee"
              name="providerFee"
              value={`${value}`}
              label="Fee"
              readOnly
            />
          </span>
    
        </div>
      );
    };

    Then the field is used in the config:

    // collection
    const orders = {
    slug: 'orders',
    fields: [
     /* ... */
            {
              name: 'providerFee',
              type: 'number',
              defaultValue: 0,
              admin: {
                condition: (data) => (data.type === 'withdrawal'),
                components: {
                  Field: ProviderFee,
                },
              },
            },
        ],
    }
  • default discord avatar
    jasonkw9
    last year

    Hi @DanRibbens,

    Thank you so much for your suggestion but I have one more question. Since my products relation field only returning the ID of the product, how do I get the price of the selected product instead? I've tried to use getDataByPath('items') which return me an array of the products I selected but price is not included inside the array.

    Here's my sample code:

    {
          name: "items",
          type: "array",
          label: "Products",
          fields: [
            {
              type: "row",
              fields: [
                {
                  name: "orderItem",
                  type: "relationship",
                  relationTo: "products",
                  required: true,
                  admin: {
                    width: "50%",
                  },
                },
                {
                  name: "productPrice",
                  type: "number",
                  defaultValue: 0,
                  admin: {
                    readOnly: true,
                    components: {
                      Field: ProductPrice,
                    },
                  },
                },
                {
                  name: "quantity",
                  type: "number",
                  required: true,
                  admin: {
                    width: "10%",
                  },
                },
              ],
            },
          ],
        },
    
    2 replies
    discord user avatar
    DanRibbens
    Payload Team
    last year

    Oh gotcha, I overlooked the relationship piece. You can do an async call out to fetch the product in your useEffect. Try this in your component:

    const orderItem: string = getDataByPath('orderItem');
    const { value, setValue } = useField({ path });
    
    useEffect(() => {
      const setPrice = async () => {
        if (orderItem) {
          const result = await fetch(`/api/products/${orderItem}`);
          if (result.ok) {
            const data = await result.json();
            setValue(data.price);
          }
        }
      }
      setPrice();
    }, [orderItem, setValue]);
    default discord avatar
    jasonkw9
    last year

    Hey @DanRibbens , thank you so much for your help! I manage to achieve what I want

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.