TypeScript Multiple DropDown Submit

Viewed 50

I have created a dropdown that multi selects data when I want to submit data single dropdown values submits and multiple dropdown data goes null any solution?

//Drop Down Data
const permission = [
  {permissionIds:1,permit:'Oliver Hansen'},
  {permissionIds:2,permit:'Van Henry'},
  {permissionIds:3,permit:'April Tucker'}
];

export default function RoleNewEditForm() {

  const [permit, setPermit] = useState<string[]>([])
  const handleChange=(event: SelectChangeEvent<string[]>)=>{
    const{
      target:{value}
    }=event;
    setPermit(
      typeof value === 'string' ? value.split(','):value
    )
  }

//Role Interface
export interface IRole {
  id?:number;
  applicationId: number | undefined;
  name: string | null;
  description: string | null;
  permissionIds:string |null;
}
  const {
    reset,
    control,
    handleSubmit,
    formState: { isSubmitting },
  } = methods;


//Submit Data here
  const onSubmit = (data: IRole) => {
    console.log(data);

  };


  return (
    <>
      <FormProvider methods={methods} onSubmit={handleSubmit(onSubmit)}>
     
                
                  <RHFTextField name="description" label="Description" />
                <FormControl>
                  <InputLabel>Permission</InputLabel>
                  <Select multiple 
                          value={permit} onChange={handleChange}  name="permissionIds" label="Permissions"
                          renderValue={(value: Array<string>) => value.length ? value.join(','): <></>}>
                    {permission.map((per=>{
                      return <MenuItem key={per.permissionIds} value={per.permissionIds}>{per.permit}</MenuItem>
                    }))}
                 
                  </Select>
                </FormControl>
      </FormProvider>
    </>
  );
};

I have added interface and submit function also with the form value So now it could be clear to detect my problem.

1 Answers

Issue

The permissionIds form state is null because this is what it is initialied to:

const defaultValues = useMemo<IRole>(
  () => ({
    id: 0,
    name: null,
    applicationId: 0,
    description: null,
    permissionIds: null // <-- initialized null
  }),
  []
);

const methods = useForm<IRole>({
  resolver: yupResolver(NewRoleSchema),
  defaultValues // <-- initial form values
});

And this part of form state is never updated since it's not controlled.

Solution

Wrap the multi-select component in the Controller component from react-hook-form and pass the appropriate props. Provide valid initial state.

import { useForm, Controller } from "react-hook-form";

...

interface IRole {
  id?: number;
  applicationId: number | undefined;
  name: string; // <-- string type
  description: string; // <-- string type
  permissionIds: string[]; // <-- string array type
}

...

const defaultValues = useMemo<IRole>(
  () => ({
    id: 0,
    name: "", // <-- string
    applicationId: 0,
    description: "", // <-- string
    permissionIds: [] // <-- empty array
  }),
  []
);

...

<FormControl>
  <InputLabel>Permission</InputLabel>
  <Controller
    name="permissionIds"
    control={control}
    render={({ field, fieldState: { error } }) => (
      <Select
        {...field}
        multiple
        label="Permissions"
        renderValue={(value: Array<string>) => value.join(",")}
      >
        {permission.map((per) => {
          return (
            <MenuItem
              key={per.permissionIds}
              value={per.permissionIds}
            >
              {per.permit}
            </MenuItem>
          );
        })}
      </Select>
    )}
  />
</FormControl>

Edit typescript-multiple-dropdown-submit

enter image description here

Related