react-jsonschema-form icon indicating copy to clipboard operation
react-jsonschema-form copied to clipboard

Set parent formdata from custom ArrayFieldTemplate

Open GoosvandenBekerom opened this issue 2 years ago • 4 comments

Prerequisites

What theme are you using?

mui

What is your question?

Hi 👋🏼

(I created an issues 2 weeks ago https://github.com/rjsf-team/react-jsonschema-form/issues/3143 but I saw later that somehow I didn't use a template, so posting it again and closing the other one)

I'm trying to create a custom view for specifically string based arrays. I would like to use the MUI-5 autocomplete component with tags as it would save a lot of real estate for our use case (https://mui.com/material-ui/react-autocomplete/#multiple-values)

I got quite far with the code snippet below in my custom ArrayFieldTemplate.

{props.schema.items.type === 'string' ? (
  <Autocomplete
    multiple
    freeSolo
    options={[]}
    onChange={(_, values, reason, details) => {
      props.formData.splice(0, props.formData.length)
      for (let i = 0; i < values.length; i++) {
        props.formData[i] = values[i]
      }
      console.log('custom ArrayFieldTemplate props.formData', props.formData)
    }}
    renderInput={(params) => (
      <TextField {...params} label={props.title} />
    )}
    renderTags={(value: readonly string[], getTagProps) =>
      value.map((option: string, index: number) =>
        (<Chip variant="outlined" label={option} {...getTagProps({index})} />))
    }
  />
)

it looks like this image

But sadly the changes to props.formData are not propagated to the parent formData, as shown in the screenshot below (I'm assuming a readonly copy is sent to children?)

image

Anyways, my question is if there is a way to update the actual formdata from a custom template? Or is this a feature you see value in?

GoosvandenBekerom avatar Oct 06 '22 19:10 GoosvandenBekerom

The challenge is that the ArrayFieldTemplate is not really designed to do what you want since it does not have access to the onChange method which the Form uses to update the formData. Your best bet is to either override the ArrayField itself or implementing a custom widget for the string array items, via the uiSchema.

To implement the custom array field, you will probably want something like:

import { getDefaultRegistry } from '@rjsf/core';
import { FieldProps } from '@rjsf/utils`;
const { ArrayField } = getDefaultRegistry().fields;

export default function CustomArrayField(props: FieldProps) {
  const { onChange, schema, formData } = props;
  if ({props.schema.items.type === 'string') {
    const handleChange = (_, values, reason, details) => {
      const newFormData = { ...formData };
      newFormData.splice(0, newFormData.length)
      for (let i = 0; i < values.length; i++) {
        newFormData[i] = values[i]
      }
      onChange(newFormData);
    }
    return (    // The rest of your implementation ... );
  }
  // Fall through to the default
  return <ArrayField {...props} />;
}

heath-freenome avatar Oct 06 '22 20:10 heath-freenome

Hi @heath-freenome , thanks for the response :)

I would like to apply this as the default for all string based arrays, would that be possible with uiSchema?

GoosvandenBekerom avatar Oct 14 '22 08:10 GoosvandenBekerom

If you updated the above array field to detect the string based arrays and do the custom onChange only for them, then you could just use the template without needing the uiSchema, by passing your CustomArrayField template AS the ArrayField template to the Form as follows:

  <Form {...otherProps} templates={{ ArrayFieldTemplate: CustomArrayField }} />

heath-freenome avatar Oct 21 '22 16:10 heath-freenome

This issue has been automatically marked as possibly close because it has not had recent activity. It will be closed if no further activity occurs. Please leave a comment if this is still an issue for you. Thank you.

stale[bot] avatar Jan 20 '24 17:01 stale[bot]

This issue was closed because of lack of recent activity. Reopen if you still need assistance.

stale[bot] avatar Feb 19 '24 19:02 stale[bot]