0
votes
  const handleChangeMultiple = (event: React.ChangeEvent<{ value: unknown }>) => {
    const { options } = event.target as HTMLSelectElement;
    const value: string[] = [];
    for (let i = 0, l = options.length; i < l; i += 1) {
      if (options[i].selected) {
        value.push(options[i].value);
      }
    }
    setPersonName(value);
  };

I just started using material UI and they have this great Select component that let you select from a list.
The code above is the sample code they provided that work for a string[], but my project is selecting from an object array.
example: {label: "string", value:"string", b: boolean}

My question is how can I modify this handleChange to work for an object array?
I try changing string[] to the dataType[] I created but I get the error "Argument of type 'string' is not assignable to parameter of type 'dataType'.


const handleChangeMultiple = (event: ChangeEvent<{ value: dataType[] }>) => {
    console.log(event.target.value)
}

When I try this, it console log the correct value selected, but when I change console.log to setValue(event.target.value), I get error value.map is not a function.

{value.map((item) => (
    option key={item.value} value={item.label}>
      {item.label}
    </option>

The code above work when console.log.

1
maybe just use JSON.stringify to convert your datas to string, and use those as option values. and on handleChangeMultiple, just get your data back with JSON.parse ?yaya

1 Answers

0
votes

Select component is using basic type to determine which options are selected (Comparing objects is not so easy). You can use the array index:

enter image description here

import React from 'react';
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles';
import InputLabel from '@material-ui/core/InputLabel';
import FormControl from '@material-ui/core/FormControl';
import Select from '@material-ui/core/Select';

const useStyles = makeStyles((theme: Theme) =>
  createStyles({
    formControl: {
      margin: theme.spacing(1),
      minWidth: 120,
      maxWidth: 300,
    },
    chips: {
      display: 'flex',
      flexWrap: 'wrap',
    },
    chip: {
      margin: 2,
    },
    noLabel: {
      marginTop: theme.spacing(3),
    },
  }),
);

interface User {
  value: string,
  label: string,
  superUser: boolean
}

const users = [{
  value: 'OliverHansen',
  label: 'Oliver Hansen',
  superUser: true
}, {
  value: 'VanHenry',
  label: 'Van Henry',
  superUser: false
}, {
  value: 'AprilTucker',
  label: 'April Tucker',
  superUser: true
}, {
  value: 'RalphHubbard',
  label: 'Ralph Hubbard',
  superUser: false
}, {
  value: 'OmarAlexander',
  label: 'Omar Alexander',
  superUser: true
}, {
  value: 'CarlosAbbott',
  label: 'Carlos Abbott',
  superUser: false
}];

export default function MultipleSelect() {
  const classes = useStyles();
  const [selectedUsers, setSelectedUsers] = React.useState<User[]>([]);
  const [selectedUserIndexes, setSelectedUserIndexes] = React.useState<number[]>([]);

  const handleChangeMultiple = (event: React.ChangeEvent<{ value: unknown }>) => {
    const { options } = event.target as HTMLSelectElement;
    const selectedUsers: User[] = [];
    const selectedUserIndexes: number[] = [];
    for (let i = 0, l = options.length; i < l; i += 1) {
      if (options[i].selected) {
        let selectedUserIndex = parseInt(options[i].value, 10);
        selectedUsers.push(users[selectedUserIndex]);
        selectedUserIndexes.push(selectedUserIndex);
      }
    }
    console.log(selectedUserIndexes, selectedUsers);
    setSelectedUserIndexes(selectedUserIndexes);
    setSelectedUsers(selectedUsers);
  };

  return (
    <div>
      <FormControl className={classes.formControl}>
        <InputLabel shrink htmlFor="select-multiple-native">
          Native
        </InputLabel>
        <Select
          multiple
          native
          value={selectedUserIndexes}
          onChange={(e) => handleChangeMultiple(e)}
          inputProps={{
            id: 'select-multiple-native',
          }}
        >
          {users.map((user, index) => (
            <option key={index} value={index}>
              {user.label} {}
            </option>
          ))}
        </Select>
      </FormControl>
    </div>
  );
}