reactjs 如何将材质ui Popper的宽度设置为其容器的宽度,同时将禁用门户设置为false

nxowjjhe  于 2023-08-04  发布在  React
关注(0)|答案(4)|浏览(112)

我用的是material-ui popper
我想让爆破器在y方向上放容器。所以我设置disableportal={false}
但是在将disableportal设置为false之后,当我给予width: 100%时,popper占据了整个浏览器的宽度,而不仅仅是容器的宽度。我不希望弹出器在x方向上离开容器,而是将其宽度调整为容器的宽度。我如何做到这一点?请检查下面的代码复制上述问题。

import ClickAwayListener from '@material-ui/core/ClickAwayListener';
import Grow from '@material-ui/core/Grow';
import Input from '@material-ui/core/Input';
import MenuItem from '@material-ui/core/MenuItem';
import MenuList from '@material-ui/core/MenuList';
import Paper from '@material-ui/core/Paper';
import Popper from '@material-ui/core/Popper';
import React from 'react';

const items = [
  'fsdfsdfsdfs',
  'shosjsadsd',
  'dsfdjhfdksfhdsf',
  'fsdfhdhhhhhhhhh',
];

export function Test() {
    const [value, setValue] = React.useState('');
    const [anchorEl, setAnchorEl] = React.useState(null);

    const handleChange = (event: any) => {
        setValue(event.target.value);
    };

    const renderChildren = () => {
        let renderItems = items;
        if (value !== '') {
          renderItems = items.filter((item: any) => item.toLowerCase().includes(value.toLowerCase()));
        }
        return renderItems.map((item: any) => {
            return (
                <MenuItem key={item}>
                    {item}
                </MenuItem>
            );
        });
    };

    const onFoucs = (event: any) => {
        setAnchorEl(event.currentTarget);
    };

    const handleClose = () => {
        setAnchorEl(null);
    };

    const popperTrans = ({ TransitionProps }: any) => {
        return (
          <Grow
            {...TransitionProps}
            style={{ transformOrigin: '0 0 0' }}
          >
            <Paper>
                <MenuList>
                    {renderChildren()}
                </MenuList>
            </Paper>
          </Grow>
        );
    };

    const open = Boolean(anchorEl);
    return (
      <div style={{width: 1000, height: 500}}>
        <ClickAwayListener onClickAway={handleClose}>
            <div>
                <Input
                    onChange={handleChange}
                    onFocus={onFoucs}
                    value={value}
                    placeholder='Search'
                    style={{width: '100%'}}
                />
                <Popper
                    open={open}
                    anchorEl={anchorEl}
                    transition={true}
                    placement='bottom-start'
                    style={{zIndex: 10000, width: '100%'}}
                >
                    {popperTrans}
                </Popper>
            </div>
        </ClickAwayListener>
      </div>
    );
}

字符串

6tr1vspr

6tr1vspr1#

我相信一定有更好的办法,但既然我找不到…
以下是我解决方法:

const [width, setWidth] = React.useState(DEFAULT_WIDTH);

useEffect(() => {
   setWidth(document.getElementById('container')?.offsetWidth);
}, [document.getElementById('container')?.offsetWidth])

<Button id="container">{text}</Button>
<Popper
    open={open}
    placement="bottom"
    style={{ zIndex: 1, width: `${width}px` }}
>
    {...children}
</Popper>

字符串

relj7zay

relj7zay2#

我不确定是什么原因导致了你的问题。我只能给你看文档中的例子。我从那里激发了我的实现,它就像一个魅力。我从您的代码示例中看到的一个不同之处是<ClickAwayListener>应该只包裹在<MenuList>周围。希望对你有帮助。

hfsqlsce

hfsqlsce3#

答案来得有点晚,但我不喜欢其他答案,这可能会帮助别人:
下面是如何使用useRef钩子解决这个问题。
我相信你也可以和你的主播一起做同样的事情。

import {useState, useRef, ReactNode} from 'react';
import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
import {
  Button,
  ButtonGroup,
  ButtonGroupProps,
  ClickAwayListener,
  Grow,
  MenuItem,
  MenuList,
  Paper,
  Popper,
} from '@mui/material';

interface Props extends ButtonGroupProps {
  primaryButton: ReactNode;
  secondaryButtons: Array<ReactNode>;
}

const SecondaryActionsButton = ({primaryButton, secondaryButtons, ...buttonGroupProps}: Props) => {
  const [open, setOpen] = useState(false);
  const anchorRef = useRef<HTMLDivElement>(null);

  const handleToggle = () => {
    setOpen(prevOpen => !prevOpen);
  };

  const handleClose = (event: Event) => {
    if (
      anchorRef.current &&
      anchorRef.current.contains(event.target as HTMLElement)
    ) {
      return;
    }

    setOpen(false);
  };

  return (
    <>
      <ButtonGroup ref={anchorRef} {...buttonGroupProps}>
        {primaryButton}
        <Button
          size="small"
          sx={{
            borderTopLeftRadius: 0,
            borderBottomLeftRadius: 0,
            borderLeft: 0,
          }}
          onClick={handleToggle}
        >
          <ArrowDropDownIcon />
        </Button>
      </ButtonGroup>
      <Popper
        sx={{
          zIndex: 1,
        }}
        open={open}
        anchorEl={anchorRef.current}
        placement="bottom-end"
        transition
        disablePortal
      >
        {({TransitionProps}) => (
          <Grow {...TransitionProps}>
            <Paper
              sx={{
                zIndex: 1,
                borderTopLeftRadius: 0,
                borderTopRightRadius: 0,
                width: anchorRef.current?.clientWidth,
                maxWidth: anchorRef.current?.clientWidth,
                overflow: 'hidden',
              }}
            >
              <ClickAwayListener onClickAway={handleClose}>
                <MenuList id="split-button-menu" autoFocusItem>
                  {secondaryButtons}
                </MenuList>
              </ClickAwayListener>
            </Paper>
          </Grow>
        )}
      </Popper>
    </>
  );
};

export default SecondaryActionsButton;

字符串

eiee3dmh

eiee3dmh4#

如果你使用的popper.js允许你覆盖middlewares设置,你可以这样做:
参考:匹配参考宽度
选择下拉列表的一个共同特征是,下拉列表匹配引用的宽度,而不管其内容如何。你也可以使用size(){:js},因为Rect{:.class}会被传入:

// size fn is the part that does the trick
// you should alter other code to fit your usage scenario
popperProps={{
  middlewares: (presetMiddlewares) => {
    return [
      ...presetMiddlewares,
      size({
        apply({ rects, elements }) {
          Object.assign(elements.floating.style, {
            width: `${rects.reference.width}px`,
          });
        },
      }),
    ];
  }
}}

字符串

相关问题