admin管理员组

文章数量:1023529

I'm using react-calendar package on my react app. Placing <Calendar/> on the file gives the open calendar on the frontend.

But I want to display the calendar if the user clicks the input field:

      <div className="form-group">
        <label>Start Date</label>
        <input type="text"/>
        <Calendar style={{display: "none"}} />
      </div>

I tried through inline style to hide the calendar ponent and change on click. But the calendar doesn't hide with inline css also.

Gone through documentation also but didn't find any help.

I'm using react-calendar package on my react app. Placing <Calendar/> on the file gives the open calendar on the frontend.

But I want to display the calendar if the user clicks the input field:

      <div className="form-group">
        <label>Start Date</label>
        <input type="text"/>
        <Calendar style={{display: "none"}} />
      </div>

I tried through inline style to hide the calendar ponent and change on click. But the calendar doesn't hide with inline css also.

Gone through documentation also but didn't find any help.

Share Improve this question asked Jun 30, 2020 at 7:45 psudopsudo 1,5783 gold badges35 silver badges85 bronze badges 3
  • 1. use a state variable like showCal: false 2. conditionally render the calendar {this.state.showCal && <Calendar />} 3. add onFocus to the input, and use it to change the showCal state to true. (react works differently than you're used to, it's all based on state and doesn't manipulate the DOM directly) – user5734311 Commented Jun 30, 2020 at 7:49
  • I have 2 calendar ponent. I assume with this approach both calendar will be shown at once . Should i declare different state for both calendar ?? – psudo Commented Jun 30, 2020 at 7:51
  • Yes, that's how it works :) – user5734311 Commented Jun 30, 2020 at 7:54
Add a ment  | 

2 Answers 2

Reset to default 4

It will be best you create a wrapper ponent around your calendar and input. This way it manages its own showCalendar state and can be reused elsewhere.

import React, { useState } from "react";
import Calendar from "react-calendar";

const ReactCalendarDemo = ({ date, setDate }) => {
  const [showCalendar, setShowCalendar] = useState(false);
  const handleChange = value => {
    setDate(value);
    setShowCalendar(false);
  };

  return (
    <div>
      <input
        value={date.toLocaleDateString()}
        onFocus={() => setShowCalendar(true)}
      />
      <Calendar
        className={showCalendar ? "" : "hide"}
        value={date}
        onChange={handleChange}
      />
    </div>
  );
};

export default ReactCalendarDemo;

You pass in your current date value and its setter as props.

Then you can toggle display in your CSS style using the hide class

.react-calendar.hide {
  display: none;
}

To achieve this functionality, integrate the react-calendar library beneath the input field. Position the calendar using CSS with position: absolute. Utilize an event listener on the document to detect clicks outside the ponent, toggling the calendar's visibility accordingly.

First create child ponent: CalendarInput. Here's a simplified example:

import React, {useState, useRef, useEffect} from "react";
import Calendar from "react-calendar";
import moment from "moment";

const CalendarInput = ({date, setDate}: {
    date: Date;
    setDate: (value: any, event: React.MouseEvent<HTMLButtonElement>) => void;
}) => {
    const [focused, setFocused] = useState(false);
    const calendarRef = useRef<HTMLDivElement>(null);

    useEffect(() => {
        const handleDocumentMousedown = (event: MouseEvent) => {
            if (
                calendarRef.current &&
                !calendarRef.current.contains(event.target as Node)
            ) {
                setFocused(false);
            }
        };

        document.addEventListener("mousedown", handleDocumentMousedown);

        return () => {
            document.removeEventListener("mousedown", handleDocumentMousedown);
        };
    }, []);

    const handleChange = (value: any, event: any) => {
        setDate(value, event);
        setFocused(false);
    };

    const handleInputClick = (event: React.MouseEvent<HTMLInputElement>) => {
        event.stopPropagation();
        setFocused(true);
    };

    return (
        <div className="w-full" ref={calendarRef}>
            <input
                className="input-default"
                value={moment(date).format("DD-MM-YYYY").toString()}
                onClick={handleInputClick}
            />
            {focused && (
                <div className="calendar-container">
                    <Calendar
                        className="absolute"
                        value={date}
                        onChange={handleChange}
                    />
                </div>
            )}
        </div>
    );
};

export default CalendarInput;

Then in your parent ponent add :

const [date, setDate] = useState(new Date());
<CalendarInput date={date} setDate={setDate} />

I'm using react-calendar package on my react app. Placing <Calendar/> on the file gives the open calendar on the frontend.

But I want to display the calendar if the user clicks the input field:

      <div className="form-group">
        <label>Start Date</label>
        <input type="text"/>
        <Calendar style={{display: "none"}} />
      </div>

I tried through inline style to hide the calendar ponent and change on click. But the calendar doesn't hide with inline css also.

Gone through documentation also but didn't find any help.

I'm using react-calendar package on my react app. Placing <Calendar/> on the file gives the open calendar on the frontend.

But I want to display the calendar if the user clicks the input field:

      <div className="form-group">
        <label>Start Date</label>
        <input type="text"/>
        <Calendar style={{display: "none"}} />
      </div>

I tried through inline style to hide the calendar ponent and change on click. But the calendar doesn't hide with inline css also.

Gone through documentation also but didn't find any help.

Share Improve this question asked Jun 30, 2020 at 7:45 psudopsudo 1,5783 gold badges35 silver badges85 bronze badges 3
  • 1. use a state variable like showCal: false 2. conditionally render the calendar {this.state.showCal && <Calendar />} 3. add onFocus to the input, and use it to change the showCal state to true. (react works differently than you're used to, it's all based on state and doesn't manipulate the DOM directly) – user5734311 Commented Jun 30, 2020 at 7:49
  • I have 2 calendar ponent. I assume with this approach both calendar will be shown at once . Should i declare different state for both calendar ?? – psudo Commented Jun 30, 2020 at 7:51
  • Yes, that's how it works :) – user5734311 Commented Jun 30, 2020 at 7:54
Add a ment  | 

2 Answers 2

Reset to default 4

It will be best you create a wrapper ponent around your calendar and input. This way it manages its own showCalendar state and can be reused elsewhere.

import React, { useState } from "react";
import Calendar from "react-calendar";

const ReactCalendarDemo = ({ date, setDate }) => {
  const [showCalendar, setShowCalendar] = useState(false);
  const handleChange = value => {
    setDate(value);
    setShowCalendar(false);
  };

  return (
    <div>
      <input
        value={date.toLocaleDateString()}
        onFocus={() => setShowCalendar(true)}
      />
      <Calendar
        className={showCalendar ? "" : "hide"}
        value={date}
        onChange={handleChange}
      />
    </div>
  );
};

export default ReactCalendarDemo;

You pass in your current date value and its setter as props.

Then you can toggle display in your CSS style using the hide class

.react-calendar.hide {
  display: none;
}

To achieve this functionality, integrate the react-calendar library beneath the input field. Position the calendar using CSS with position: absolute. Utilize an event listener on the document to detect clicks outside the ponent, toggling the calendar's visibility accordingly.

First create child ponent: CalendarInput. Here's a simplified example:

import React, {useState, useRef, useEffect} from "react";
import Calendar from "react-calendar";
import moment from "moment";

const CalendarInput = ({date, setDate}: {
    date: Date;
    setDate: (value: any, event: React.MouseEvent<HTMLButtonElement>) => void;
}) => {
    const [focused, setFocused] = useState(false);
    const calendarRef = useRef<HTMLDivElement>(null);

    useEffect(() => {
        const handleDocumentMousedown = (event: MouseEvent) => {
            if (
                calendarRef.current &&
                !calendarRef.current.contains(event.target as Node)
            ) {
                setFocused(false);
            }
        };

        document.addEventListener("mousedown", handleDocumentMousedown);

        return () => {
            document.removeEventListener("mousedown", handleDocumentMousedown);
        };
    }, []);

    const handleChange = (value: any, event: any) => {
        setDate(value, event);
        setFocused(false);
    };

    const handleInputClick = (event: React.MouseEvent<HTMLInputElement>) => {
        event.stopPropagation();
        setFocused(true);
    };

    return (
        <div className="w-full" ref={calendarRef}>
            <input
                className="input-default"
                value={moment(date).format("DD-MM-YYYY").toString()}
                onClick={handleInputClick}
            />
            {focused && (
                <div className="calendar-container">
                    <Calendar
                        className="absolute"
                        value={date}
                        onChange={handleChange}
                    />
                </div>
            )}
        </div>
    );
};

export default CalendarInput;

Then in your parent ponent add :

const [date, setDate] = useState(new Date());
<CalendarInput date={date} setDate={setDate} />

本文标签: javascriptShow react calendar on clickStack Overflow