Google-maps-react: InfoWindow javascript events not triggering for within window

Created on 3 Feb 2017  路  7Comments  路  Source: fullstackreact/google-maps-react

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>

Most helpful comment

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"));
  }

Here is a working example.

All 7 comments

@ 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"));
  }

Here is a working example.

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"));
  }

Here is a working example.

Thank you so much for this!!!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lishi500 picture lishi500  路  4Comments

carmen79 picture carmen79  路  4Comments

Vijayan-Murugan picture Vijayan-Murugan  路  4Comments

ktosiek picture ktosiek  路  3Comments

cernoel picture cernoel  路  3Comments