Simplify your stack and build anything. Or everything.
Build tomorrow’s web with a modern solution you truly own.
Code-based nature means you can build on top of it to power anything.
It’s time to take back your content infrastructure.

Populate value to read only field

default discord avatar
jasonkw92 years ago
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

  • Selected Answer
    discord user avatar
    DanRibbens
    2 years ago

    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
    jasonkw92 years ago

    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
    2 years ago

    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
    jasonkw92 years ago

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

Star on GitHub

Star

Chat on Discord

Discord

online

Can't find what you're looking for?

Get dedicated engineering support directly from the Payload team.