InfoWindow javascript events not triggering for within window
None of the buttons ... A ,B ,C ,D do not fire... i ahve been trying links, buttons and header elements all do not fire events
<InfoWindow
marker={this.state.activeMarker}
visible={this.state.showingInfoWindow}>
<div>
<button onClick={() => {this.setState({ showingInfoWindow:false });}}>A</button>
<button onClick={(e) => {this.setState({ showingInfoWindow:false });}}>B</button>
<button onClick={(e) => {e.preventDefault();console.log(e);}}>C</button>
<button onClick={this.onClickMarkerAgentName}>D</button>
</div>
</InfoWindow>
@ CapnMorgan71 : do you find any solution on it ? i am also getting same problem.
Running into the same issue. The problem is the way the actual HTML that is passed to the Google InfoWindow is rendered.
The library uses renderToString from react-dom/server, which is obviously used in server-side rendering. It just renders a component to HTML, but what it does not do, is actually registering any client-side React stuff to it, so event handlers won't work.
I think it needs some kind of way of passing it through ReactDOM.render() or something.
To make this work, You can pass a div with an Id to InfoWindow. Then in onMarkerClick you can render any elements that need to respond to mouse events using ReactDOM.render(). Thanks, @dmeenhuis sending me down that path.
Hi, I ran into the same issue, and fixed it with Corey's method. Here some code for the beginners like me. All of that is in InfoWindow.js obviously.
Start by adding a div to the InfoWindow
const iw = this.infowindow = new google.maps.InfoWindow({ content: '<div id="iwc"/>' });
Now when updating the content (so in method updateContent), use ReactDOM.render(React.Children.only(children), document.getElementById("iwc"));
This assumes your InfoWindow has a single child, so use a container or modify this.
At this point, this won't work as updateContent is called before the InfoWindow is actually open. So change the test in componentDidUpdate to
if (this.props.visible && prevProps.visible && this.props.children !== prevProps.children) {
this.updateContent();
}
Now you just need to update the content when opening the window, so add this.updateContent() in openWindow.
Hope that helps!
Hi All, Thanks for all your comments. I manage to build (after reading your suggestions) an example that works without modifying the Infowindow code.
The infoWindow itself should only contain a placeholder div with a unique id:
<InfoWindow
marker={this.state.activeMarker}
visible={this.state.showingInfoWindow}
onOpen={e => {
this.onInfoWindowOpen(this.props, e);
}}
>
<div id="iwc" />
</InfoWindow>
And inside the Mapcontainer, you define an onInfoWindowOpen callback, that inserts a single component/container with the onClick event and render it to a placeholder div:
onInfoWindowOpen(props, e) {
const button = (<button onClick={e => {console.log("hmapbuttoni1");}}>mapbutton</button>);
ReactDOM.render(React.Children.only(button), document.getElementById("iwc"));
}
Another approach is to use portals:
class ElementInfoWindow extends InfoWindow {
renderInfoWindow() {
InfoWindow.prototype.renderInfoWindow.call(this);
this.elem = document.createElement('div');
}
renderChildren() {
return this.elem;
}
render() {
const {children} = this.props;
return this.elem ? ReactDOM.createPortal(children, this.elem) : null;
}
}
Hi All, Thanks for all your comments. I manage to build (after reading your suggestions) an example that works without modifying the Infowindow code.
The infoWindow itself should only contain a placeholder div with a unique id:
<InfoWindow marker={this.state.activeMarker} visible={this.state.showingInfoWindow} onOpen={e => { this.onInfoWindowOpen(this.props, e); }} > <div id="iwc" /> </InfoWindow>And inside the Mapcontainer, you define an onInfoWindowOpen callback, that inserts a single component/container with the onClick event and render it to a placeholder div:
onInfoWindowOpen(props, e) { const button = (<button onClick={e => {console.log("hmapbuttoni1");}}>mapbutton</button>); ReactDOM.render(React.Children.only(button), document.getElementById("iwc")); }
Thank you so much for this!!!
Another approach is to use portals:
class ElementInfoWindow extends InfoWindow { renderInfoWindow() { InfoWindow.prototype.renderInfoWindow.call(this); this.elem = document.createElement('div'); } renderChildren() { return this.elem; } render() { const {children} = this.props; return this.elem ? ReactDOM.createPortal(children, this.elem) : null; } }
Thank you so much this work in react 18