Search code examples
javascriptreactjsantd

Getting content of currently active Text component wrapped inside popover of antd


I am using antd components for my react app. I have a Text component wrapped inside of Popover component. Now in my case this Popover is applied to one particular column of table, i.e. every row-element in that column has a Popover component rendered for it upon mouse hovering.


    title: "Name",
    dataIndex: "name",
    key: "name-key",
    sortType: "string",
    sortDirections: ["descend", "ascend"],
    sorter: (a, b) => a.name.length - b.name.length,
    render: (text, record) => (

    <Popover>
    <Text onMouseOver={handleOnMouseOverCommitId}> {name} </Text>
    </Popover>

)

I want to get hold of the row-element's value, the one contained by the above Text component whenever I hover over it. In this case the value denoted by {name} above.

I tried getting it with e.target.value via onMouseOver event, but it returned undefined.

I think I get the reason behind it, because the event.target returns an html node of type <span>.

With a normal div element e.target.value has worked in the past for me. But doing the same thing with a predefined component like antd's Text seems a bit trickier.

Just to elaborate, the Popover has two buttons and based on which button user clicks, I need to render some other components, something like an overlay component.

But in order to do that I would also need to get hold of the text value which originally triggered the Popover.

Below is the code(most of the things removed for preciseness).

record.name is what I ultimately need to capture.

    <Popover
        content={
            <>
                <Space>
                    <Button onClick={showSomeOverlayPaneForName}>
                        {"View Details for record.name"}
                    </Button>
                    <Button href={"https://abc.xyz.com/" + record.role}>
                        {"View Role Details"}
                    </Button>
                </Space>
            </>
        }
        trigger={"hover"}
    >
        <Text style={{"color": blue.primary}} copyable={true} onMouseOver={handleOnMouseOverName}>{record.name}</Text>
    </Popover>

The handleOnMouseOverName function(which doesn't work anyway) :

const handleOnMouseOverName = (e) => {
    //console.log("e.target.value :--- ", e.target.value);
    setCurrentActiveName(e.target.value)
}

And once my currentActiveName variable is set(via useState), I use that value inside my function showSomeOverlayPaneForName


const showSomeOverlayPaneForName = (e) => {
    axios
        .get(
            `some-url`,
            {
                params: {name: currentActiveName}
            }
        )
        .then((response) => {
            setData(response.data);

        }).catch(reason => {
        //xyz
    });
}



Solution

  • You need to pass on the record of the enclosing render function to the handleOnMouseOverName function.

    Check the following example

    
        import React from 'react';
        import 'antd/dist/antd.css';
        import './index.css';
        import { Space, Table, Button, Popover } from 'antd';
    
        const App = () => {
          const data = [
            {
              key: '1',
              name: 'John Brown',
              address: 'New York No. 1 Lake Park',
              role: 'admin',
            },
            {
              key: '2',
              name: 'Jim Green',
              address: 'London No. 1 Lake Park',
              role: 'user',
            },
            {
              key: '3',
              name: 'Joe Black',
              address: 'Sidney No. 1 Lake Park',
              role: 'manager',
            },
          ];
    
          const columns = [
            {
              title: 'Name',
              dataIndex: 'name',
              key: 'name',
              render: (name, record) => {
                const content = (
                  <>
                    <Space>
                      <Button
                        onClick={() => {
                          viewDetail(record);
                        }}
                      >
                        {'View Details for ' + record.name}
                      </Button>
                      <Button href={'https://abc.xyz.com/' + record.role}>
                        {'View Role Details'}
                      </Button>
                    </Space>
                  </>
                );
                return (
                  <>
                    <Popover content={content} title="Details">
                      <div
                        onMouseOver={() => {
                          handleOnMouseOverName(record);
                        }}
                      >
                        {name}
                      </div>
                    </Popover>
                  </>
                );
              },
            },
            {
              title: 'Address',
              dataIndex: 'address',
              key: 'address',
            },
          ];
    
          const handleOnMouseOverName = (record) => {
            console.log(record);
          };
    
          const viewDetail = (record) => {
            console.log(record);
          };
    
          return <Table columns={columns} dataSource={data} />;
        };
    
        export default App;
    
    

    Output:

    GIF

    I hope this helps.