Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there a better way to display InfoWindow? #333

Closed
brandonmp opened this issue Sep 7, 2016 · 6 comments
Closed

Is there a better way to display InfoWindow? #333

brandonmp opened this issue Sep 7, 2016 · 6 comments

Comments

@brandonmp
Copy link

looking at this example and a few things occur to me:

  • the mechanism for showing the window seems like an anti-pattern. it skips entirely the React management of state and props and just mutates an internal variable. is there a more 'react-y' pattern for this?
  • i use Immutable.js and pass my marker locations down through props. obviously i can't mutate props, so according to the pattern in the example, I should create an intermediate array of markers between props and render()? This seems really counter intuitive
  • Because it's instantiating an InfoWindow with each marker, there's potential to have dozens of instances of the element at any one time. again this seems far less efficient than the normal way (ie, render 1 InfoWindow, and dynamically tell it where to open)

I was looking at instead using a Popover from the MUI library, but that requires a DOM Element to determine the location it should open at

I'm also looking at the Google Maps API, and it looks like you can pass InfoWindow map coordinates. this would work great, but how do I pass that info to InfoWindow?

@brandonmp
Copy link
Author

brandonmp commented Sep 7, 2016

After some messing around with it I arrived at this solution which I think will be more performant than the example.

if the devs agree that this is better i can submit a pr for a new example

a method in my map component:

InfoWindow can open at a specific coordinate, so we'll use the coordinate of the clicked marker.

First we control the visibility of the InfoWindow by placing its location in state, then write a toggle method. Basically, if windowPosition == null, window is closed, else windowPosition == {lat, lng}

 toggleInfoWindow = (loc) => {
    // clicking 'x' in the info window will pass null, so if we detect that, reset the position in state
    if (loc == null) {
      this.setState({ windowPosition: null })
      return
    }
    // otherwise get coords of clicked marker and set to state
    let markerLoc = { lat: loc.latLng.lat(), lng: loc.latLng.lng() }
    this.setState({ windowPosition: markerLoc })
  }

then inside our GoogleMap component, we create an <InfoWindow> component:

 <InfoWindow
                  position={this.state.windowPosition}
                  onCloseclick={this.toggleInfoWindow}
                  options={{pixelOffset: new google.maps.Size(0,-30)}}
                  >
  content
</InfoWindow>

note the options prop. because the InfoWindow is opened @ same point as our marker, if we don't offset it, it will cover the marker and look bad. this option moves the infoWindow up 30 pixels.

Lastly, in our Marker component, call the toggle method onClick:

<Marker
{...props}
onClick={this.toggleInfoWindow}
/>

@tomchentw
Copy link
Owner

@brandonmp <InfoWindow> can of course rendered separated without <Marker>. Yes an position props could do that!

Also, 6.0.0 is released on npm beta tag now. We also have a new demo page. Feel free to try it:
https://tomchentw.github.io/react-google-maps/

@alengel
Copy link

alengel commented Mar 19, 2017

Hi @brandonmp, thank you for your example! I was able to use it and got my map to only show one InfoWindow at a time now.

I do have the issue you mention about the InfowWindow being exactly on top of the Marker and I'm struggling to figure out how to use the pixelOffset with this library.

screen shot 2017-03-19 at 11 32 22 am

I've imported the following at the top of my file:

import { InfoWindow } from 'react-google-maps';

and I've tried to add the options like this:

<InfoWindow 
        defaultPosition={ this.props.position }
        user={ this.props.user }
        options={{pixelOffset: new google.maps.Size(0,-30)}}
        mapHolderRef={ this.props.mapHolderRef } >
   { ... my content }
</InfoWindow> 

but I don't have access to google and can't figure out how to access the Size class as per Google's docs. I've also tried importing google-maps directly but that didn't work. I think probably because I use the react-google-maps library everywhere else. How did you get access to the Size class? I can't see it as part of this library?

Feeling a bit stumped and any help would be very appreciated!

@nguyenvanphuc2203
Copy link

nguyenvanphuc2203 commented Mar 13, 2018

Try use onClick inside html code , it work for me 💃

<InfoWindow  onCloseClick={props.onToggleOpen}>
            <div onClick={()=>{alert('hello')}} class="wow slideInLeft">
              <img src="https://i.imgur.com/7IgBxnH.jpg" width="150px" />
              <div>nhà trọ cho thuê</div>
              <div>1.500.000đ</div>
            </div>
</InfoWindow>

@cfdesign
Copy link

cfdesign commented Sep 17, 2018

Hi @brandonmp, thank you for your example! I was able to use it and got my map to only show one InfoWindow at a time now.

I do have the issue you mention about the InfowWindow being exactly on top of the Marker and I'm struggling to figure out how to use the pixelOffset with this library.

screen shot 2017-03-19 at 11 32 22 am

I've imported the following at the top of my file:

import { InfoWindow } from 'react-google-maps';

and I've tried to add the options like this:

<InfoWindow 
        defaultPosition={ this.props.position }
        user={ this.props.user }
        options={{pixelOffset: new google.maps.Size(0,-30)}}
        mapHolderRef={ this.props.mapHolderRef } >
   { ... my content }
</InfoWindow> 

but I don't have access to google and can't figure out how to access the Size class as per Google's docs. I've also tried importing google-maps directly but that didn't work. I think probably because I use the react-google-maps library everywhere else. How did you get access to the Size class? I can't see it as part of this library?

Feeling a bit stumped and any help would be very appreciated!

@alengel
I am very new to React and I am also struggling to comprehend the 'loose' documentation that accompanies the majority of various unofficial React Google Maps libraries that are available.

I have a load of markers on my map, which I also only wanted one info window to open at a time. To avoid multiple info windows, I decided not to have them as children of every marker; Rather a single <InfoWindow> as a sibling of <Marker> & child of <GoogleMap>. When a <Marker> is clicked, it's lat, lng is then made stateful & used to position the <InfoWindow>.

As my <InfoWindow> is a separate component I have to introduce an offset so that it doesn't open directly above it's <Marker>. Through A LOT of trial and error I have come to the conclusion that anything that would usually require 'google.map' needs 'window' declared before hand. So for example

`<Markers
animation={window.google.maps.Animation.DROP}

`

Therefore to achieve the offset on an <InfoWindow> try:

`<InfoWindow
options={{pixelOffset: new window.google.maps.Size(0,-40)}}

`

I know this solution address's a now very old query, but I do hope that this will help someone else in future and save a lot of time!

@jiehan1029
Copy link

@cfdesign Thank you tremendously. I also encountered the 'google' not defined problem, and your answer saved me!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants