簡體   English   中英

MATERIAL-UI React - 另一個波普爾的波普爾

[英]MATERIAL-UI React - Popper of another Popper

我正在開發一個日歷應用程序。

問題:單擊 popper 的 popper 會關閉兩個 popper,因為它會觸發關閉它的第一個 popper 的 click outside 事件。

我有一個組件<Event />它使用 Material-UI React <Popper />並且它可以正常工作。 將它與<AwayClickListener />相結合,它在單擊外側時關閉,在彈出器內部單擊時保持打開狀態。 我創建了<Events />這是<Event />的列表。

事件詳情波普爾

單擊 + 更多文本時,應在單元格頂部顯示包含當天所有事件的彈出器。

popper 孩子也是<Events />

擴展事件列表

單擊一個事件應該會打開一個帶有事件詳細信息的彈出器,就像在單元格中單擊它一樣。 因為我使用相同的組件<Events />它這樣做,但不完全符合預期:

單擊事件詳細信息彈出器會關閉兩個彈出器。

這就是問題所在:要求是單擊彈出器的外側將關閉彈出器,但單擊內部將使它們保持打開和交互

事件列表彈出器及其事件詳細信息彈出器

調試顯示單擊第二個 popper 會觸發第一個 popper 的外部單擊事件,從而將其關閉。 此外,從第一個彈出器中取出點擊離開監聽器 function 讓第二個彈出器在大多數點擊中保持打開狀態 - 單擊其中的某些位置,觸發它被點擊離開 function 關閉它。 例如:單擊標題將其關閉,單擊位置或摘要 div 不會。

  1. 我嘗試用<ClickAwayListener />包裹整個單元格。
  2. 我嘗試用<ClickAwayListener />包裝 popper 的孩子
  3. 嘗試使用material-ui-popup-state npm,並給出popper id屬性。 比點擊離開時,將目標 ID 與“popper”進行比較,如果相等則保持打開狀態。 但是,從 onClickAway 事件的事件 object 中提取的 id 是空字符串。 即使單擊彈出器。

代碼

<Popper> - 材質 ui popper 的服裝包裝器

const popper = ({
  placement,
  open,
  anchorEl,
  handleClickAway=null,
  title,
  handleCloseClick=null,
  children,
  popperStyle = {},
  calendarPopoverClass = ''
}) => {
  const useStyles = makeStyles({
    Popper: popperStyle
  })
  const styles = useStyles();
  return (
    <Popper modifiers={{
      flip: {
        enabled: false,
      },
      preventOverflow: {
        enabled: false,
        boundariesElement: 'scrollParent',
      }
    }}
      className={styles.Popper}
      placement={placement}
      open={open}
      anchorEl={anchorEl}
    >
      <ClickAwayListener onClickAway={handleClickAway}>
        <CalendarPopover className={st(classes[calendarPopoverClass])} isShown withArrow={false} title={title} onClose={handleCloseClick}>
          {children}
        </CalendarPopover>
      </ClickAwayListener>
    </Popper>
  )
}

<Event />

const event = ({ PROPS }) => {
const [expanded, setExpanded] = React.useState(null);
const closeExpanded = () => setExpanded(null)
return (
        <>
          <div
            className={st(classes.Event, { isTimeShown, isNextWeekFirstFiller, isLastFiller, isMultiDay, isAllDay, isFiller })}
            style={inlineStyle}
            onClick={onEventClick}
          >
            <div className={classes.Time}>{timeToDisplay}</div>
            <div className={classes.Title}>{title}</div>
          </div>
          <Popper
      placement={popperPlacement}
      title={title}
      handleCloseClick={closeExpanded}
      handleClickAway={closeExpanded}
      open={Boolean(expanded)}
      anchorEl={expanded}
      popperStyle={popperStyle}
      calendarPopoverClass='Event'
    >
      <ExpandedEvent
        startDate={startDate}
        endDate={endDate}
        location={location}
        summary={summary}
      />
    </Popper>
        </>
      );
}

<Events />

const Events = ({ events, isTimeShown, localeToggle, popperPlacement, popperStyle, handleShowMoreClick=null }) => {
  const eventsToShow: JSX.Element[] = [];
  if (events.length > 0) {
    let eventsToShowAmount = 3;
    const moreEventsCount = events.length - eventsToShowAmount;
    eventsToShowAmount = moreEventsCount > 0 ? eventsToShowAmount : events.length;
    for (let i = 0; i < eventsToShowAmount; i++) {
      eventsToShow.push(
        <Event
          key={events[i].id}
          {...events[i]}
          isTimeShown={isTimeShown}
          popperPlacement={popperPlacement}
          popperStyle={popperStyle}
        />
      )
    }
    if (moreEventsCount > 0) {
      eventsToShow.push(<ShowMore key='ShowMore' handleClick={handleShowMoreClick} moreEventsCount={moreEventsCount} />)
    }
  }

  return (
    <div className={classes.Events}>
      {eventsToShow}
    </div>
  );
}

<MonthlyCell />

const MonthlyCell = ({
  events,
  isTimeShown,
  popperPlacement,
  popperStyle
}) => {

  const [expandedEvents, setExpandedEvents] = React.useState(null);
  const cell = React.useRef<HTMLDivElement>(null)


  const eventsList = (handleShowMoreClick = null) => (
    <Events
      events={events}
      isTimeShown={isTimeShown}
      localeToggle={true}
      popperPlacement={popperPlacement}
      popperStyle={popperStyle}
      handleShowMoreClick={handleShowMoreClick}
    />
  );

  const handleShowMoreClick = () => setExpandedEvents(eventsList());

  const closeExpandedEvents = () => {
    setExpandedEvents(null);
  }

  return (
    <>
      <div ref={cell} className={classes.MonthlyCell} >
        {eventsList(handleShowMoreClick)}
      </div>
      <Popper
        placement='left'
        open={Boolean(expandedEvents)}
        title='hello'
        handleClickAway={closeExpandedEvents}
        anchorEl={cell.current}
        popperStyle={{ left: '17% !important' }}
        handleCloseClick={closeExpandedEvents}
      >
        {eventsList()}
      </Popper>
    </>
  );
}

希望它足夠清楚。 讓我知道是否需要其他任何東西。 謝謝

編輯 1

另一種嘗試是給父 popper 更大的 z-index,但它沒有用

解決方案是將popper孩子包圍在一個div中。 我使用的組件導致了這種不需要的行為,因為它沒有 forwardRef 支持。 所以添加 div 包裝器解決了這個問題。

另外,刪除修飾符屬性:

<Popper 
      // modifiers={{
      // flip: {
      //  enabled: false,
      // },
      // preventOverflow: {
      //   enabled: false,
      //   boundariesElement: 'scrollParent',
     //  }
    // }}

工作解決方案的鏈接: https://codesandbox.io/s/popper-in-a-popper-s6dfr?file=/src/Popper/Popper.js:372-519

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM