Search code examples
javascriptreactjsantdpopover

open ant design popover from two link


I have two component: 1:StudentList 2: Major in react and antd.

StudentList Component rendered a list of students. Major Component made a list of majors that you can pick them. After selecting major, the selected major title display on the top of the students list. and the list will be filtered according to the selected major.

This is StudentList component contain Major component:

class StudentList extends Component {

  render(){
    return(
      <>
      <Major/>
      <h5>20 student found in <a>selected major</a></h5>
     
      <List>
      //this is the list of students and is not related to this question
      </List>
      </>);
  }
 }

This is Major Component with a filter button to open the popover:

class Major extends Component {
  render() {
    return (
      <Popover
        trigger="click"
        content={content} //list of majors
      >
        <Button>
            <FilterOutlined /> Select major to filter
        </Button>
      </Popover>
    );
  }
}

When I click on the Select major to filter button, the popover open to select majors. I want to change the code in order to open this popover from two place:

1- click on Select major to filter button in the Major component

2- click on selected major in the title in StudentList component.

Notice: I want to open the same popover in the same place (similar to when I click on Select major to filter button)

Maybe it could handle with state and handleVisibleChange function. but I don't know how to handle it from 2 components. I glad to hearing your solutions.


Solution

  • You can use the visible and onVisibleChange property from Antd's tooltip because they are used by the PopOver as well. You can find an easy example from Andt how to control a PopOver by visible in the docs.

    To get the button click you can use onClick from antd's Button Api.

    The desired example using React Components:

    class Major extends Component {
      componentDidUpdate(prevProps) {
        // Typical usage (don't forget to compare props):
        if (this.props.value !== prevProps.value) {
          this.setState({ visible: this.props.value });
        }
      }
    
      state = {
        visible: false
      };
    
      hide = () => {
        this.setState({
          visible: false
        });
      };
    
      handleVisibleChange = visible => {
        this.setState({ visible });
        // this.props.onChange(visible); // add me to open popover on every click on studenlist
      };
    
      render() {
        return (
          <Popover
            trigger="click"
            content={<a onClick={this.hide}>Close</a>}
            visible={this.state.visible}
            onVisibleChange={this.handleVisibleChange}
          >
            <Button>Select major to filter</Button>
          </Popover>
        );
      }
    }
    
    class StudentList extends Component {
      state = {
        visible: false
      };
    
      onClick = () => {
        this.setState({ visible: !this.state.visible });
      };
    
      render() {
        return (
          <>
            {/* <Major value={this.state.visible} onChange={setVisible} /> */}
            <Major value={this.state.visible} />
            <h5>
              20 student found in <a>selected major</a>
            </h5>
    
            <Button onClick={this.onClick}>Select major from Studenlist</Button>
          </>
        );
      }
    }
    

    Component example as a CodeSandBox.


    Here is a simple example for your request using react hooks and simple buttons to open the PopOver:

    function Major({ value, onChange }) {
      const [visible, setVisible] = useState(value);
      useEffect(() => {
        value && setVisible(value);
      }, [value]);
    
      const hide = () => setVisible(false);
    
      const handleVisibleChange = visible => {
        setVisible(visible);
        onChange(visible);
      };
    
      return (
        <Popover
          trigger="click"
          content={<a onClick={hide}>Close</a>}
          visible={visible}
          onVisibleChange={handleVisibleChange}
        >
          <Button>Select major to filter</Button>
        </Popover>
      );
    }
    
    function StudentList() {
      const [visible, setVisible] = useState(false);
      const onClick = () => {
        setVisible(true);
      };
    
      return (
        <>
          <Major value={visible} onChange={setVisible} />
          <h5>
            20 student found in <a>selected major</a>
          </h5>
    
          <Button onClick={onClick}>Select major from Studenlist</Button>
        </>
      );
    }
    

    The depended working CodeSandBox.


    Edit1: Added React Component example.