Reputation: 30785
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
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
Reputation: 9523
Alternatives:
Create 20 handlers (which I know you don't want to do)
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.
Embed an identifier in your anchor element that you then key off of in your handlers with a big switch or if-elseif chain.
Write a handlerCreator function that returns a closure that encapsulates the identifier when the handlerCreate function returns the function closure.
Upvotes: 0