Populate value to read only field

default discord avatar
jasonkw9last 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

  • Selected Answer
    discord user avatar
    DanRibbens
    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
    jasonkw9last 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
    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
    jasonkw9last year

    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 help straight from the Payload team with an Enterprise License.