mui-x icon indicating copy to clipboard operation
mui-x copied to clipboard

[pickers] DatePicker date selection part jump else where

Open neo-lu15 opened this issue 1 year ago • 4 comments

Steps to reproduce

Link to live example: (required) 螢幕擷取畫面 2024-10-15 170051

Steps:

import dayjs from 'dayjs';

import { DatePicker } from '@mui/x-date-pickers/DatePicker'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'

body() { const { showChecklist, checklistData, startDate, endDate, showDateFilter } = this.state;

return (
  <LocalizationProvider dateAdapter={AdapterDayjs}>
  <div>
    {!showChecklist ? (
      <>
        <div>
          <Input
            placeholder="Calendar Name"
            value={this.state.inputText}
            onChange={(e) => this.handleInputChange(e)}
          />
          <Button
            icon={<ArrowRight16Filled />}
            onClick={() => this.handleSearchClick()}
          >
            Search
          </Button>
        </div>
      </>
    ) : (
      <div className="list-body">
        <div>
          <Input
            placeholder="Calendar Name"
            value={this.state.inputText}
            onChange={(e) => this.handleInputChange(e)}
          />
          <Button
            icon={<ArrowRight16Filled />}
            onClick={() => this.handleSearchClick()}
          >
            Search
          </Button>
        </div>
        
        <div >
          {checklistData.map((item) => {
            return(
            <div key={item.id} >
              <div className="divider" />

              <Checkbox
                className="checkbox"
                label=""
                onChange={(e, checked) => this.handleCheckboxChange(item.id, checked)}
              />
              <div className="meeting-info">
                <Link className="title" href={item.webLink} target="_blank">
                  {item.subject}
                </Link>
                <Text className="content">
                  {item.organizer.emailAddress.name}
                </Text>
                <DatePicker
                  label="Start Date"
                  defaultValue={dayjs(item.recurrence.range.startDate)}
                  value={startDate}
                  slotProps={{
                    // The actions will be the same between desktop and mobile
                    actionBar: {
                      actions: ['clear'],
                    },
                    // The actions will be different between desktop and mobile
                    actionBar: ({ wrapperVariant }) => ({
                      actions: wrapperVariant === 'desktop' ? [] : ['clear'],
                    }),
                  }}
                  onSelectDate={(date) => this.handleDateChange("startDate", date)}
                />
                <DatePicker
                  label="End Date"
                  defaultValue={dayjs(item.recurrence.range.endtDate)}
                  value={endDate}
                  slotProps={{ popper: { placement: 'bottom-end' }}}
                  onSelectDate={(date) => this.handleDateChange("endDate", date)}
                />
              </div>
            </div>);
          })}
        </div>
        
        {showDateFilter && (
          <div className="date-filter">
            
            <Button onClick={() => this.filterEventsByDate()}>
              Apply Date Filter
            </Button>
          </div>
        )}

      </div>
    )}
  </div>
  </LocalizationProvider>
);

}

Current behavior

where i use calender to choose date it popped to the up page

Expected behavior

it has to be under the datpicker

Context

can you help me with this what's wrong?

Your environment

npx @mui/envinfo body() { const { showChecklist, checklistData, startDate, endDate, showDateFilter } = this.state;
return (
  <LocalizationProvider dateAdapter={AdapterDayjs}>
  <div>
    {!showChecklist ? (
      <>
        <div>
          <Input
            placeholder="Calendar Name"
            value={this.state.inputText}
            onChange={(e) => this.handleInputChange(e)}
          />
          <Button
            icon={<ArrowRight16Filled />}
            onClick={() => this.handleSearchClick()}
          >
            Search
          </Button>
        </div>
      </>
    ) : (
      <div className="list-body">
        <div>
          <Input
            placeholder="Calendar Name"
            value={this.state.inputText}
            onChange={(e) => this.handleInputChange(e)}
          />
          <Button
            icon={<ArrowRight16Filled />}
            onClick={() => this.handleSearchClick()}
          >
            Search
          </Button>
        </div>
        
        <div >
          {checklistData.map((item) => {
            return(
            <div key={item.id} >
              <div className="divider" />

              <Checkbox
                className="checkbox"
                label=""
                onChange={(e, checked) => this.handleCheckboxChange(item.id, checked)}
              />
              <div className="meeting-info">
                <Link className="title" href={item.webLink} target="_blank">
                  {item.subject}
                </Link>
                <Text className="content">
                  {item.organizer.emailAddress.name}
                </Text>
                <DatePicker
                  label="Start Date"
                  defaultValue={dayjs(item.recurrence.range.startDate)}
                  value={startDate}
                  onSelectDate={(date) => this.handleDateChange("startDate", date)}
                />
                <DatePicker
                  label="End Date"
                  defaultValue={dayjs(item.recurrence.range.endtDate)}
                  value={endDate}
                  slotProps={{ popper: { placement: 'bottom-end' }}}
                  onSelectDate={(date) => this.handleDateChange("endDate", date)}
                />
              </div>
            </div>);
          })}
        </div>

      </div>
    )}
  </div>
  </LocalizationProvider>
);

}

  Don't forget to mention which browser you used.
  Output from `npx @mui/envinfo` goes here.
螢幕擷取畫面 2024-10-15 170051

Search keywords: datepicker

neo-lu15 avatar Oct 15 '24 09:10 neo-lu15

Hello @neo-lu15,

I didn't manage to reproduce your issue with the provided information. It could be very helpful if you can share a live example using tools like stackblitz, for instance.

Do not hesitate to get ping us once you update the issue ! 🙂

arthurbalduini avatar Oct 15 '24 10:10 arthurbalduini

Hi @arthurbalduini I'm using developing the outlook addin and using the datapicker i'm not sure will it influence or not my modules are "dependencies": { "@azure/msal-browser": "^3.18.0", "@emotion/react": "^11.13.3", "@emotion/styled": "^11.13.0", "@fluentui/react-charting": "^5.14.10", "@fluentui/react-components": "^9.18.0", "@fluentui/react-icons": "^2.0.186", "@microsoft/microsoft-graph-client": "^3.0.7", "@microsoft/microsoft-graph-types": "^2.40.0", "@microsoft/teams-js": "^2.19.0", "@microsoft/teamsfx": "^2.2.0", "@microsoft/teamsfx-react": "^3.0.0", "@mui/material": "^6.1.3", "@mui/x-date-pickers": "^7.20.0", "d3": "^7.9.0", "d3-brush": "^3.0.0", "d3-selection": "^3.0.0", "dayjs": "^1.11.13", "react": "^18.2.0", "react-d3-tree": "^3.6.2", "react-dom": "^18.2.0", "react-helmet-async": "^2.0.5", "react-router-dom": "^6.8.0", "react-scripts": "^5.0.1" },

my codes are import "../styles/DownloadCalendarAttachmentWidget.css"; import dayjs from 'dayjs';

import { DatePicker } from '@mui/x-date-pickers/DatePicker'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs' import { Text, Button, Input, Spinner, Checkbox, Link } from "@fluentui/react-components"; import { ArrowRight16Filled, MoreHorizontal32Regular, ArrowDownload24Regular } from "@fluentui/react-icons"; import { BaseWidget } from "@microsoft/teamsfx-react"; import { SearchEvent, downloadAttachment } from "../services/services";

export default class DownloadCalendarAttachmentWidget extends BaseWidget { constructor(props) { super(props); this.state = { inputText: "", loading: false, showChecklist: false, checklistData: [], selectedEventIds: [], // Track selected events' IDs showDateFilter: false, // Control visibility of the date filter startDate: null, endDate: null }; }

async getData() { // If you need to fetch any initial data, do it here return {}; }

header() { return (

<ArrowDownload24Regular /> <Text>Download Calendar Attachment</Text> <Button icon={<MoreHorizontal32Regular />} appearance="transparent" />
); }

body() { const { showChecklist, checklistData, startDate, endDate, showDateFilter } = this.state;

return (
  <LocalizationProvider dateAdapter={AdapterDayjs}>
  <div>
    {!showChecklist ? (
      <>
        <div>
          <Input
            placeholder="Calendar Name"
            value={this.state.inputText}
            onChange={(e) => this.handleInputChange(e)}
          />
          <Button
            icon={<ArrowRight16Filled />}
            onClick={() => this.handleSearchClick()}
          >
            Search
          </Button>
        </div>
      </>
    ) : (
      <div className="list-body">
        <div>
          <Input
            placeholder="Calendar Name"
            value={this.state.inputText}
            onChange={(e) => this.handleInputChange(e)}
          />
          <Button
            icon={<ArrowRight16Filled />}
            onClick={() => this.handleSearchClick()}
          >
            Search
          </Button>
        </div>
        
        <div >
          {checklistData.map((item) => {
            return(
            <div key={item.id} >
              <div className="divider" />

              <Checkbox
                className="checkbox"
                label=""
                onChange={(e, checked) => this.handleCheckboxChange(item.id, checked)}
              />
              <div className="meeting-info">
                <Link className="title" href={item.webLink} target="_blank">
                  {item.subject}
                </Link>
                <Text className="content">
                  {item.organizer.emailAddress.name}
                </Text>
                <DatePicker
                  label="Start Date"
                  defaultValue={dayjs(item.recurrence.range.startDate)}
                  value={startDate}
                  slotProps={{
                    // The actions will be the same between desktop and mobile
                    actionBar: {
                      actions: ['clear'],
                    },
                    // The actions will be different between desktop and mobile
                    actionBar: ({ wrapperVariant }) => ({
                      actions: wrapperVariant === 'desktop' ? [] : ['clear'],
                    }),
                  }}
                  onSelectDate={(date) => this.handleDateChange("startDate", date)}
                />
                <DatePicker
                  label="End Date"
                  defaultValue={dayjs(item.recurrence.range.endtDate)}
                  value={endDate}
                  slotProps={{ popper: { placement: 'bottom-end' }}}
                  onSelectDate={(date) => this.handleDateChange("endDate", date)}
                />
              </div>
            </div>);
          })}
        </div>
        
        {showDateFilter && (
          <div className="date-filter">
            
            <Button onClick={() => this.filterEventsByDate()}>
              Apply Date Filter
            </Button>
          </div>
        )}

      </div>
    )}
  </div>
  </LocalizationProvider>
);

}

loading() { return <Spinner>Loading...</Spinner>; }

footer() { return ( <><Button appearance="primary">View Details</Button><Button id="download-footer" appearance="transparent" icon={<ArrowRight16Filled />} iconPosition="after" size="small" onClick={() => this.handleDownloadClick()} // Trigger download on button click > Download </Button></> ); }

handleInputChange(e) { this.setState({ inputText: e.target.value }); }

async handleSearchClick() { console.log("Search button clicked"); console.log(this.state.inputText); this.setState({ loading: true });

try {
  const events = await SearchEvent(this.state.inputText);
  this.setState({
    checklistData: events, // Assuming events is an array of event objects
    filteredData: events,
    showChecklist: true,
    loading: false,
  });
} catch (error) {
  console.error("Error downloading attachment:", error);
  this.setState({ loading: false });
}

}

handleCheckboxChange(id) { console.log(handleCheckboxChange called with id: ${id});

this.setState(prevState => {
  const isCurrentlySelected = prevState.selectedEventIds.includes(id);
  console.log(`ID ${id} is currently ${isCurrentlySelected ? 'selected' : 'not selected'}`);

  let newSelectedEventIds;

  if (isCurrentlySelected) {
    // Remove the ID if it's currently selected
    newSelectedEventIds = prevState.selectedEventIds.filter(eventId => eventId !== id);
    console.log(`Removed ${id} from selected IDs`);
  } else {
    // Add the ID if it's not currently selected
    newSelectedEventIds = [...prevState.selectedEventIds, id];
    console.log(`Added ${id} to selected IDs`);
  }

  const showDateFilter = newSelectedEventIds.length > 0;

  console.log("New selected event IDs:", newSelectedEventIds);
  console.log("Show date filter:", showDateFilter);

  return {
    selectedEventIds: newSelectedEventIds,
    showDateFilter: showDateFilter
  };
});

}

handleDateChange(field, date) { this.setState({ [field]: date }); }

filterEventsByDate() { const { checklistData, startDate, endDate } = this.state;

const filteredData = checklistData.filter((event) => {
  const eventDate = new Date(event.start.dateTime);
  return (!startDate || eventDate >= startDate) && (!endDate || eventDate <= endDate);
});

this.setState({ filteredData });

}

async handleDownloadClick() { const { selectedEventIds } = this.state;

if (selectedEventIds.length === 0) {
  alert("No events selected for download.");
  return;
}

// Loop through each selected event ID and download its attachments
for (let eventId of selectedEventIds) {
  try {
    await downloadAttachment(eventId);
  } catch (error) {
    console.error("Error downloading attachment for event:", eventId, error);
  }
}

} }

neo-lu15 avatar Oct 16 '24 02:10 neo-lu15

@arthurbalduini Hi i found out that when the browser zoom out 67% the pickdate part is perfect but when the web zoom in above 67% the gap bewteen the block and pickdate is larger Is this normal?

neo-lu15 avatar Oct 17 '24 09:10 neo-lu15

Hello @neo-lu15

Could you please provide a minimal reproducible example using CodeSandbox, StackBlitz, or any similar tool? It's difficult to extract the relevant details from the code in your last comment.

For guidance, you can refer to this issue as an example of how to organize information effectively so we can assist you better! 🙂

arthurbalduini avatar Oct 17 '24 12:10 arthurbalduini

The issue has been inactive for 7 days and has been automatically closed.

github-actions[bot] avatar Oct 24 '24 15:10 github-actions[bot]