简体   繁体   English

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

[英]How to set the width of material ui Popper to its container's width while setting disable portal as false

I am using material-ui popper .我正在使用material-ui 波普尔

I want to let the popper go put of container in y-direction.我想让 popper go 在 y 方向放置容器。 So I set disableportal={false} .所以我设置disableportal={false}

But after setting disableportal to false, when I give width: 100% , popper is occupying the entire browser's width instead of just it's container's width.但是在将disableportal设置为 false 后,当我给出width: 100%时,popper 会占据整个浏览器的宽度,而不仅仅是容器的宽度。 I don't want the popper to go out of container in x direction but adjust it's width to the width of it's container.我不希望 popper 在 x 方向上超出容器 go,但将其宽度调整为容器的宽度。 How do I achieve this?我如何实现这一目标? Please check below code for reproducing the above issue.请检查以下代码以重现上述问题。

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>
    );
}

I'm not sure about what is causing the issue for you.我不确定是什么导致了您的问题。 I can only point you to the example in the docs .我只能指出 文档中的示例。 I inspired my implementation from there and it worked like a charm.我从那里激发了我的实施,它就像一个魅力。 One difference that I see from your code sample is that the <ClickAwayListener> should be only wrapped around the <MenuList> .我从您的代码示例中看到的一个区别是<ClickAwayListener>应该只包裹在<MenuList>周围。 Hope it helps.希望能帮助到你。

I'm sure there must be a better way to do this, but since I couldn't find one...我敢肯定一定有更好的方法来做到这一点,但因为我找不到...

here is my workaround:这是我的解决方法:

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>

If you are using popper.js that allows you to override middlewares setting , you could do this:如果您使用的 popper.js 允许您覆盖中间件设置,您可以这样做:

Reference: Match reference width参考: 匹配参考宽度

A common feature of select dropdowns is that the dropdown matches the width of the reference regardless of its contents. select 下拉菜单的一个共同特征是无论其内容如何,下拉菜单都与引用的宽度匹配。 You can also use size(){:js} for this, as the Rect{:.class}s get passed in:您也可以为此使用 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`,
          });
        },
      }),
    ];
  }
}}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM