如何在传输列表上设置来自 rails 服务器的参数?

How can I set params from rails server on Transfer List?


我正在使用 material ui。

我想将 rails 中的数据设置到传输列表中。
我的参数是这样的:

0: {id: 1, name: 'Rank A', deleted_at: null, created_at: '2017-09-13T00:54:26.000+09:00', updated_at: '2017-09-13T00:54:26.000+09:00'}
1: {id: 2, name: 'Rank B', deleted_at: null, created_at: '2017-09-13T00:54:27.000+09:00', updated_at: '2017-09-13T00:54:27.000+09:00'}
2: {id: 3, name: 'Rank C', deleted_at: null, created_at: '2017-09-13T00:54:27.000+09:00', updated_at: '2017-09-13T00:54:27.000+09:00'}
3: {id: 4, name: 'Keep', deleted_at: null, created_at: '2017-09-13T00:54:27.000+09:00', updated_at: '2017-09-13T00:54:27.000+09:00'}
4: {id: 5, name: 'Blacklist', deleted_at: null, created_at: '2017-09-13T00:54:27.000+09:00', updated_at: '2017-09-13T00:54:27.000+09:00'}
5: {id: 8, name: 'Withdrawal', deleted_at: null, created_at: '2017-09-13T00:54:27.000+09:00', updated_at: '2017-09-13T00:54:27.000+09:00'}
6: {id: 9, name: 'On sale', deleted_at: null, created_at: '2019-02-08T18:57:24.000+09:00', updated_at: '2019-02-08T18:57:24.000+09:00'}
7: {id: 10, name: 'Change email', deleted_at: null, created_at: '2020-10-28T19:47:25.000+09:00', updated_at: '2020-10-28T19:47:25.000+09:00'}

来自materialui文档,类型为数字

https://mui.com/components/transfer-list/#TransferList.tsx

我试过适配代码:

import * as React from "react";
import Grid from "@mui/material/Grid";
import List from "@mui/material/List";
import ListItem from "@mui/material/ListItem";
import ListItemIcon from "@mui/material/ListItemIcon";
import ListItemText from "@mui/material/ListItemText";
import Checkbox from "@mui/material/Checkbox";
import Button from "@mui/material/Button";
import Paper from "@mui/material/Paper";

interface TransferListProps {
  evaluation: any;
}

function not(a: readonly number[], b: readonly number[]) {
  console.log(a.filter((value) => b.indexOf(value) === -1));
  return a.filter((value) => b.indexOf(value) === -1);
}

function intersection(a: readonly number[], b: readonly number[]) {
  return a.filter((value) => b.indexOf(value) !== -1);
}

export default function TransferList(props: TransferListProps) {
  const [checked, setChecked] = React.useState<readonly number[]>([]);
  const [left, setLeft] = React.useState<readonly number[]>([0, 1, 2, 3, 4]);
  const [right, setRight] = React.useState<readonly number[]>([]);

  const leftChecked = intersection(checked, left);
  const rightChecked = intersection(checked, right);

  const handleToggle = (value: number) => () => {
    const currentIndex = checked.indexOf(value);
    const newChecked = [...checked];

    if (currentIndex === -1) {
      newChecked.push(value);
    } else {
      newChecked.splice(currentIndex, 1);
    }

    setChecked(newChecked);
  };

  const handleAllRight = () => {
    setRight(right.concat(left));
    setLeft([]);
  };

  const handleCheckedRight = () => {
    setRight(right.concat(leftChecked));
    setLeft(not(left, leftChecked));
    setChecked(not(checked, leftChecked));
  };

  const handleCheckedLeft = () => {
    setLeft(left.concat(rightChecked));
    setRight(not(right, rightChecked));
    setChecked(not(checked, rightChecked));
  };

  const handleAllLeft = () => {
    setLeft(left.concat(right));
    setRight([]);
  };

  const customList = (items: readonly number[]) => (
    <Paper sx={{ width: 175, height: 230, overflow: "auto" }}>
      <List dense component="div" role="list">
        {props.evaluation.map((value: any) => {
          const labelId = `transfer-list-item-${value}-label`;

          console.log(props.evaluation);

          return (
            <ListItem
              key={value}
              role="listitem"
              button
              onClick={handleToggle(value.id)}
            >
              <ListItemIcon>
                <Checkbox
                  checked={checked.indexOf(value.id) !== -1}
                  tabIndex={-1}
                  disableRipple
                  inputProps={{
                    "aria-labelledby": labelId,
                  }}
                />
              </ListItemIcon>
              <ListItemText id={labelId} primary={`${value.name}`} />
            </ListItem>
          );
        })}
        <ListItem />
      </List>
    </Paper>
  );

  return (
    <Grid container spacing={2} justifyContent="start" alignItems="center">
      <Grid item>{customList(left)}</Grid>
      <Grid item>
        <Grid container direction="column" alignItems="center">
          <Button
            sx={{ my: 0.5 }}
            variant="outlined"
            size="small"
            onClick={handleAllRight}
            disabled={left.length === 0}
            aria-label="move all right"
          >
            ≫
          </Button>
          <Button
            sx={{ my: 0.5 }}
            variant="outlined"
            size="small"
            onClick={handleCheckedRight}
            disabled={leftChecked.length === 0}
            aria-label="move selected right"
          >
            &gt;
          </Button>
          <Button
            sx={{ my: 0.5 }}
            variant="outlined"
            size="small"
            onClick={handleCheckedLeft}
            disabled={rightChecked.length === 0}
            aria-label="move selected left"
          >
            &lt;
          </Button>
          <Button
            sx={{ my: 0.5 }}
            variant="outlined"
            size="small"
            onClick={handleAllLeft}
            disabled={right.length === 0}
            aria-label="move all left"
          >
            ≪
          </Button>
        </Grid>
      </Grid>
      <Grid item>{customList(right)}</Grid>
    </Grid>
  );
}

但是当我select左边的时候,右边也检查了。

我该如何解决?
谢谢。

我解决了

重要的是在useState中使用map方法。

import * as React from "react";
import Grid from "@mui/material/Grid";
import List from "@mui/material/List";
import ListItem from "@mui/material/ListItem";
import ListItemIcon from "@mui/material/ListItemIcon";
import ListItemText from "@mui/material/ListItemText";
import Checkbox from "@mui/material/Checkbox";
import Button from "@mui/material/Button";
import Paper from "@mui/material/Paper";

interface TransferListProps {
  evaluation: any;
}

function not(a: readonly number[], b: readonly number[]) {
  console.log(a.filter((value) => b.indexOf(value) === -1));
  return a.filter((value) => b.indexOf(value) === -1);
}

function intersection(a: readonly number[], b: readonly number[]) {
  return a.filter((value) => b.indexOf(value) !== -1);
}

export default function TransferList(props: TransferListProps) {
  const [checked, setChecked] = React.useState<readonly any[]>([]);
  const [left, setLeft] = React.useState<any[]>(
    props.evaluation.map((value: any) => {
      return value.name;
    })
  );
  const [right, setRight] = React.useState<any[]>([]);

  const leftChecked = intersection(checked, left);
  const rightChecked = intersection(checked, right);

  const handleToggle = (value: number) => () => {
    const currentIndex = checked.indexOf(value);
    const newChecked = [...checked];
    console.log([...checked]);

    if (currentIndex === -1) {
      newChecked.push(value);
    } else {
      newChecked.splice(currentIndex, 1);
    }

    setChecked(newChecked);
  };

  const handleAllRight = () => {
    setRight(right.concat(left));
    setLeft([]);
  };

  const handleCheckedRight = () => {
    setRight(right.concat(leftChecked));
    setLeft(not(left, leftChecked));
    setChecked(not(checked, leftChecked));
  };

  const handleCheckedLeft = () => {
    setLeft(left.concat(rightChecked));
    setRight(not(right, rightChecked));
    setChecked(not(checked, rightChecked));
  };

  const handleAllLeft = () => {
    setLeft(left.concat(right));
    setRight([]);
  };

  const customList = (items: string[]) => (
    <Paper sx={{ width: 175, height: 230, overflow: "auto" }}>
      <List dense component="div" role="list">
        {items.map((value: any) => {
          const labelId = `transfer-list-item-${value}-label`;

          return (
            <ListItem
              key={value}
              role="listitem"
              button
              onClick={handleToggle(value)}
            >
              <ListItemIcon>
                <Checkbox
                  checked={checked.indexOf(value) !== -1}
                  tabIndex={-1}
                  disableRipple
                  inputProps={{
                    "aria-labelledby": labelId,
                  }}
                />
              </ListItemIcon>
              <ListItemText id={labelId} primary={`${value}`} />
            </ListItem>
          );
        })}
        <ListItem />
      </List>
    </Paper>
  );

  return (
    <Grid container spacing={2} justifyContent="start" alignItems="center">
      <Grid item>{customList(left)}</Grid>
      <Grid item>
        <Grid container direction="column" alignItems="center">
          <Button
            sx={{ my: 0.5 }}
            variant="outlined"
            size="small"
            onClick={handleAllRight}
            disabled={left.length === 0}
            aria-label="move all right"
          >
            ≫
          </Button>
          <Button
            sx={{ my: 0.5 }}
            variant="outlined"
            size="small"
            onClick={handleCheckedRight}
            disabled={leftChecked.length === 0}
            aria-label="move selected right"
          >
            &gt;
          </Button>
          <Button
            sx={{ my: 0.5 }}
            variant="outlined"
            size="small"
            onClick={handleCheckedLeft}
            disabled={rightChecked.length === 0}
            aria-label="move selected left"
          >
            &lt;
          </Button>
          <Button
            sx={{ my: 0.5 }}
            variant="outlined"
            size="small"
            onClick={handleAllLeft}
            disabled={right.length === 0}
            aria-label="move all left"
          >
            ≪
          </Button>
        </Grid>
      </Grid>
      <Grid item>{customList(right)}</Grid>
    </Grid>
  );
}