Is there a way not to close the antd dropdown menu by clicking on it?

Viewed 4328

Im trying to implement an Antd Dropdown Menu with Search functionality, and wanted to close the dropdown when clicking outside. But in my code, along with clicking outside even if I click on the Search box, it toggles opening and closing of the dropdown(not desired). I want my dropdown menu to be open only if there is some character input in the search box and close if there is no character in the search box or if clicked outside, and it should not open and close if I go on just clicking on the search box itself. Is there any prop Im missing out on? Here is the sample code:

import React from "react";
import ReactDOM from "react-dom";
import "antd/dist/antd.css";
import "./index.css";
import { Menu, Dropdown, Input } from "antd";

class OverlayVisible extends React.Component {
  state = {
    visible: false
  };

  handleMenuClick = (e) => {
    if (e.key === "3") {
      this.setState({ visible: false });
    }
  };

  handleVisibleChange = (flag) => {
    this.setState({ visible: flag });
  };

  render() {
    const menu = (
      <Menu onClick={this.handleMenuClick}>
        <Menu.Item key="1">Clicking me will not close the menu.</Menu.Item>
      </Menu>
    );
    return (
      <Dropdown
        onClick={() => {
          this.setState({ visible: true });
        }}
        overlay={menu}
        onVisibleChange={this.handleVisibleChange}
        visible={this.state.visible}
        trigger={["click"]}
      >
        <Input.Search
          onInput={() => {
            this.setState({ visible: true });
          }}
        ></Input.Search>
        {/* <a className="ant-dropdown-link" onClick={e => e.preventDefault()}>
          Hover me <Icon type="down" />
        </a> */}
      </Dropdown>
    );
  }
}

ReactDOM.render(<OverlayVisible />, document.getElementById("container"));

CodeSandbox Link: https://codesandbox.io/s/aman-521r2?file=/index.js:0-1236

3 Answers

I think you can do this by changing Input Search m

<Input.Search
          onChange={(e) => {
         
            if (e.target.value.length) {

              this.setState({ visible: true });
              return false;
            }
            this.setState({ visible: false });
          }}
        ></Input.Search>

and remove setstate from handleVisibleChange

  handleVisibleChange = (flag) => {
 
  };

Add one more state for storing input values.

 state = {
    visible: false,
    value: ''
  };

Now set the value state when user type the value in the input

<Input.Search
   onInput={() => {
     this.setState({ visible: true });
   }}
   onChange={e => this.setState({value: e.target.value})}
   />

Now control the visibility of dropdown with the help of the length of the value.

  handleVisibleChange = (flag) => {
    if(this.state.value.length <= 0)
     this.setState({ visible: false });
    else
     this.setState({ visible: flag });
  };

Full code:

import React from "react";
import ReactDOM from "react-dom";
import "antd/dist/antd.css";
import "./index.css";
import { Menu, Dropdown, Input } from "antd";

class OverlayVisible extends React.Component {
  state = {
    visible: false,
    value: ''
  };

  handleMenuClick = (e) => {
    if (e.key === "3") {
      this.setState({ visible: false });
    }
  };

  handleVisibleChange = (flag) => {
    if(this.state.value.length<=0)
    this.setState({ visible: false });
    else
    this.setState({ visible: flag });
  };

  render() {
    const menu = (
      <Menu onClick={this.handleMenuClick}>
        <Menu.Item key="1">Clicking me will not close the menu.</Menu.Item>
      </Menu>
    );
    return (
      <Dropdown
        onClick={() => {
          this.setState({ visible: true });
        }}
        overlay={menu}
        onVisibleChange={this.handleVisibleChange}
        visible={this.state.visible}
        trigger={["click"]}
      >
        <Input.Search
          onInput={() => {
            this.setState({ visible: true });
          }}
          onChange={e => this.setState({value: e.target.value})}
        ></Input.Search>
        {/* <a className="ant-dropdown-link" onClick={e => e.preventDefault()}>
          Hover me <Icon type="down" />
        </a> */}
      </Dropdown>
    );
  }
}

ReactDOM.render(<OverlayVisible />, document.getElementById("container"));

Ran into the same issue and solved by adding onClick={(e) => e?.stopPropagation()} to the container where the click should not close the overlay

Related