Green
Green

Reputation: 30785

Popover doesn't work if you have many of them on one page. How to manage them?

Examples here http://www.material-ui.com/#/components/popover are valid for one Popover element on the page only. If one follows their examples it is not possible to have more than one Popover on one page. Because Popovers begin interfering each other.

For example. Here is a markup for a single popover. And imagine that you have ten of these in one page:

<div onClick={this.openPopover}>Open Popover</div>
<Popover
    open={this.state.open}
    anchorEl={this.state.anchorEl}
    anchorOrigin={{horizontal: 'left', vertical: 'bottom'}}
    targetOrigin={{horizontal: 'left', vertical: 'top'}}
    onRequestClose={this.closePopover}
    animated={true}
    >
    <div style={{padding: '20px'}}>
        <p>Hello World</p>
    </div>
</Popover>

Here is their React handlers according to material-ui.com examples. And with this, if I trigger one popover, all of them are opened. Because this.state.open is common for every popover:

getInitialState() {
    return {
        open: false,
    };
},

    openPopover(event) {
        this.setState({
            open: true,
            anchorEl: event.currentTarget,
        });
    },
    closePopover(reason: string) {
        this.setState({
             open: false,
        });
    },

I want to have only those two handlers - openPopover and closePopover. I do not want to create 20 separate handlers for my 10 popovers.

Because of strange signature of closePopover function (for some reason they made it to expects a string instead of an event or an anchorElement) it is not possible to pass it anything to determine property on-the-fly as ES6 allows, for example:

getInitialState() {
    return {
        popover1: false,
    };
},

    // e.g. getAttribute('data-name') == 'popover1'
    // <div onClick={this.openPopover} data-name="popover1">Open Popover</div>

    openPopover(event) {
        this.setState({
            [event.currentTarget.getAttribute('data-name')]: true,
            anchorEl: event.currentTarget,
        });
    },

    // and here instead of useless "reason: string", an event or anchorElement would do the trick
    closePopover(reason: string) {
        this.setState({
             [event.currentTarget.getAttribute('data-name')]: false,
        });
    },

What is material-ui.com best practice to have multiple popovers in one page? Hope the answer isn't to create a separate React Popover class for each popover on the page. Also hope it is not to create a separate handler functions for each and every popover.

Upvotes: 0

Views: 3511

Answers (2)

Sijan Bhandari
Sijan Bhandari

Reputation: 3051

The right way of dealing with multiple similar material-ui components is binding name with the callback function.

For example you have to deal with two popover : Define state identifier for each popover like following at your constructor :

this.state = {
    first : false,
    second: false,
    };

Then you can call individual popover actions with:

onTouchTap={this.handleTouchTap.bind(this, 'first')} 

onTouchTap={this.handleTouchTap.bind(this, 'second')} 

and finally at your handleTouchTap function, you can define :

handleTouchTap(name, event, index, value) {


    event.preventDefault();
    var change = {};
    change[name] = true;

    this.setState(change)

  };

This don't need to create multiple handlers. You just need bind name to identify them.

Upvotes: 1

Larry Maccherone
Larry Maccherone

Reputation: 9523

Alternatives:

  1. Create 20 handlers (which I know you don't want to do)

  2. Depending upon what they are attached to, you may be able to create your own component that encapsulates the field/title/etc and popover. If all your fields are of the same type, that should be easy. If you have 5, then you'll need to create 5 different components.

  3. Embed an identifier in your anchor element that you then key off of in your handlers with a big switch or if-elseif chain.

  4. Write a handlerCreator function that returns a closure that encapsulates the identifier when the handlerCreate function returns the function closure.

Upvotes: 0

Related Questions