Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calendar 日历组件 怎么点击非当前月日期的时候,让面板不跳转呢。 #48394

Open
ImpTyrion opened this issue Apr 11, 2024 · 13 comments

Comments

@ImpTyrion
Copy link

What problem does this feature solve?

给每个日期框添加 PopOver 时,面板跳转会导致 PopOver位置不对,即时可以通过代码控制,也会出现同时出现两个 PopOver,因为日期作为key

What does the proposed API look like?

改为属性可配置
是否跟这条更新有关,#47361

@afc163 afc163 added the 🤔 Need Reproduce We cannot reproduce your problem label Apr 15, 2024
Copy link
Contributor

Hello @JimWang-happy. Please provide a online reproduction by forking codesandbox of antd@5.x or antd@4.x, or provide a minimal GitHub repository. Issues labeled by Need Reproduce will be closed if no activities in 3 days.

你好 @JimWang-happy,我们需要你提供一个在线的重现实例以便于我们帮你排查问题。你可以通过点击这里创建一个 antd@5.xantd@4.x 的 codesandbox,或者提供一个最小化的 GitHub 仓库。3 天内未跟进此 issue 将会被自动关闭。

什么是最小化重现,为什么这是必需的?

@ImpTyrion
Copy link
Author

https://stackblitz.com/edit/react-yvn9pk-fstu5s?file=demo.tsx
重现步骤:
1 点击当前面板跨月日期,无法保证 popover 正常显示

@afc163 afc163 removed the 🤔 Need Reproduce We cannot reproduce your problem label Apr 15, 2024
@wanpan11
Copy link
Contributor

出现两个 PopOver 是因为没有显示传入 open=false (demo传入的是undefined)😂

image


可以用 disabledDate 禁用其他月份的日期(禁用跳转)

import React, { useState } from "react";
import { Calendar, Popover } from "antd";
import dayjs from "dayjs";
import type { Dayjs } from "dayjs";

const App: React.FC = () => {
  const [current, setCurrent] = useState(dayjs());

  const dateCellRender = () => {
    return (
      <Popover
        content={
          <div>
            <button>按钮</button>
          </div>
        }
        trigger="click"
        placement="right"
      >
        <div
          style={{
            width: "100%",
            height: "100%",
          }}
        ></div>
      </Popover>
    );
  };

  const cellRender = (current: Dayjs, info: any) => {
    if (info.type === "date") return dateCellRender();
    return info.originNode;
  };

  return (
    <Calendar
      cellRender={cellRender}
      onPanelChange={value => setCurrent(value)}
      disabledDate={date => {
        return dayjs(date).month() !== dayjs(current).month();
      }}
    />
  );
};

export default App;

@ImpTyrion
Copy link
Author

ImpTyrion commented Apr 17, 2024

好的,谢谢!第一个问题竟然是没显示传 false 。。。
第二个问题,禁用是可以阻止跳转,但不想阻止 Popover 呢,意思是并不是完全禁用该日期的所有行为,只是想让它不跳转。

@wanpan11
Copy link
Contributor

第二个问题,禁用是可以阻止跳转,但不想阻止 Popover 呢,意思是并不是完全禁用该日期的所有行为,只是想让它不跳转。

试试这个 我魔改了下,后面我问问大佬们,要不要支持点击不跳转 😶‍🌫️

import React, { useEffect, useRef, useState } from "react";
import { Calendar, Popover } from "antd";
import dayjs from "dayjs";
import type { Dayjs } from "dayjs";

const App: React.FC = () => {
  const containerRef = useRef<HTMLDivElement>(null);

  const [currentDate, setCurrentDate] = useState(dayjs());
  const [itemWidth, setItemWidth] = useState(0);

  const dateCellRender = (current: Dayjs) => {
    const allowSelect = dayjs(current).month() === dayjs(currentDate).month();

    return (
      <Popover
        content={
          <div>
            <button>按钮</button>
          </div>
        }
        trigger="click"
        placement="right"
      >
        <div
          onClick={evt => !allowSelect && evt.stopPropagation()}
          style={{
            width: itemWidth,
            height: "100%",
            position: "absolute",
            top: 0,
            left: 0,
          }}
        ></div>
      </Popover>
    );
  };

  const cellRender = (current: Dayjs, info: any) => {
    if (info.type === "date") return dateCellRender(current);
    return info.originNode;
  };

  // eslint-disable-next-line react-hooks/exhaustive-deps
  useEffect(() => {
    if (containerRef.current) {
      const { clientWidth } = containerRef.current;
      setItemWidth((clientWidth - 7 * 8) / 7); // 7 * 8 每个盒子的 margin
    }
  });

  return (
    <div ref={containerRef}>
      <Calendar cellRender={cellRender} onPanelChange={value => setCurrentDate(value)} onSelect={date => console.log("[ date ] ===>", date)} />
    </div>
  );
};

export default App;

@ImpTyrion
Copy link
Author

点击 Popover 空白部分还是会跳转
image

@wanpan11
Copy link
Contributor

冒泡改一下就行了

import React, { useEffect, useRef, useState } from "react";
import { Calendar, Popover } from "antd";
import dayjs from "dayjs";
import type { Dayjs } from "dayjs";

const App: React.FC = () => {
  const containerRef = useRef<HTMLDivElement>(null);

  const [currentDate, setCurrentDate] = useState(dayjs());
  const [itemWidth, setItemWidth] = useState(0);

  const dateCellRender = (current: Dayjs) => {
    const allowSelect = dayjs(current).month() === dayjs(currentDate).month();

    return (
      <div onClick={evt => !allowSelect && evt.stopPropagation()}>
        <Popover
          content={
            <div>
              <button>按钮</button>
            </div>
          }
          trigger="click"
          placement="right"
        >
          <div
            style={{
              width: itemWidth,
              height: "100%",
              position: "absolute",
              top: 0,
              left: 0,
            }}
          ></div>
        </Popover>
      </div>
    );
  };

  const cellRender = (current: Dayjs, info: any) => {
    if (info.type === "date") return dateCellRender(current);
    return info.originNode;
  };

  // eslint-disable-next-line react-hooks/exhaustive-deps
  useEffect(() => {
    if (containerRef.current) {
      const { clientWidth } = containerRef.current;
      setItemWidth((clientWidth - 7 * 8) / 7); // 7 * 8 每个盒子的 margin
    }
  });

  return (
    <div ref={containerRef}>
      <Calendar cellRender={cellRender} onPanelChange={value => setCurrentDate(value)} onSelect={date => console.log("[ date ] ===>", date)} />
    </div>
  );
};

export default App;

@ImpTyrion
Copy link
Author

好的,感谢,想让 popover 受控好像又有问题了呢😂
https://stackblitz.com/edit/react-yvn9pk-tlyy8a?file=demo.tsx

@wanpan11
Copy link
Contributor

好的,感谢,想让 popover 受控好像又有问题了呢😂 https://stackblitz.com/edit/react-yvn9pk-tlyy8a?file=demo.tsx

import React, { useEffect, useRef, useState } from "react";
import { Calendar, Popover } from "antd";
import dayjs from "dayjs";
import type { Dayjs } from "dayjs";

const App: React.FC = () => {
  const containerRef = useRef<HTMLDivElement>(null);
  const [itemWidth, setItemWidth] = useState(0);

  const [currentDate, setCurrentDate] = useState(dayjs());
  const [curPopVisible, setCurPopVisible] = useState("");

  const dateCellRender = (current: Dayjs) => {
    const allowSelect = dayjs(current).month() === dayjs(currentDate).month();

    return (
      <div
        onClick={evt => {
          setCurPopVisible(current.format("YYYY-MM-DD"));
          !allowSelect && evt.stopPropagation();
        }}
      >
        <Popover
          content={
            <div>
              <span
                style={{ display: "block" }}
                onClick={() => {
                  setTimeout(() => {
                    setCurPopVisible("");
                  });
                }}
              >
                X
              </span>
              <button>按钮</button>
            </div>
          }
          trigger="click"
          placement="right"
          open={curPopVisible === current.format("YYYY-MM-DD") || false}
        >
          <div
            style={{
              width: itemWidth,
              height: "100%",
              position: "absolute",
              top: 0,
              left: 0,
            }}
          ></div>
        </Popover>
      </div>
    );
  };

  const cellRender = (current: Dayjs, info: any) => {
    if (info.type === "date") return dateCellRender(current);
    return info.originNode;
  };

  // eslint-disable-next-line react-hooks/exhaustive-deps
  useEffect(() => {
    if (containerRef.current) {
      const { clientWidth } = containerRef.current;
      setItemWidth((clientWidth - 7 * 8) / 7); // 7 * 8 每个盒子的 margin
    }
  });

  return (
    <div ref={containerRef}>
      <Calendar cellRender={cellRender} onPanelChange={value => setCurrentDate(value)} onSelect={value => setCurPopVisible(value.format("YYYY-MM-DD"))} />
    </div>
  );
};

export default App;

@ImpTyrion
Copy link
Author

👍,这里一定要延迟才能关闭,是为啥呢,popover 内部状态的问题?
image

@wanpan11
Copy link
Contributor

处理下事件冒泡就行了

image

@ImpTyrion
Copy link
Author

为啥阻止下冒泡就行了呢🤔

@ImpTyrion
Copy link
Author

点击这个 margin 的di地方依然会跳转
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants