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

How can I "edit" Polygons and update state to match? #278

Closed
zeroasterisk opened this issue Jun 8, 2016 · 13 comments
Closed

How can I "edit" Polygons and update state to match? #278

zeroasterisk opened this issue Jun 8, 2016 · 13 comments

Comments

@zeroasterisk
Copy link

zeroasterisk commented Jun 8, 2016

If I allow editable polygons, I can listen for onMouseup and get back some "stuff" but I don't see anything which tells me which polygon I've just updated.

I have this.state.polygons as an array of polygon objects which contain paths...

[{"id":0,"editable":true,"path":[{"lat":38.25764366831546,"lng":-85.7516598701477},{"lat":38.25656530505969,"lng":-85.75185298919678},{"lat":38.25808174881664,"lng":-85.75474977493286}],"area":16623.009493033773,"options":{"fillColor":"#caebba"}}]

What I'm looking for is (I think) a way to update state from what happens to be drawn/edited... either for all Polygons, or for the edited one... but I can't seem to find a listener which tells me which one it is...

NOTE - I know that if I draw the polygons with drawing tools, I have events onOverlaycomplete and onPolygoncomplete to use and link into w/ more options (raw google map objects) but that doesn't help me when I create with <Polygon />

@iamgutz
Copy link

iamgutz commented Sep 9, 2016

@zeroasterisk You need to use refs for the polygon that triggered the event.
For Example, something like this:
assign a ref name to each polygon
const refs = 'polygon' + index
set the polygon component adding the ref name and on the mousedown event pass a function that will receive the ref name as well.
<Polygon ref={refs} center={polygon.center} paths={polygon.paths} options={polygon.options} onMousedown={() => { this._onMousedown(refs) }} editable />

_onMousedown = (ref) => {
get the reference to the googlemap and to the specific polygon (with the ref param)
const polygon = this.refs['googleMap'].refs[ref].getPath()
add event listeners for the polygon changes and pass the polygon as parameter to the function you need
google.maps.event.addListener(polygon, 'set_at', () => { this._getPolygonNewPaths(polygon) })
google.maps.event.addListener(polygon, 'insert_at', () => { this._getPolygonNewPaths(polygon) })
google.maps.event.addListener(polygon, 'remove_at', () => { this._getPolygonNewPaths(polygon) })
}

on this function you receive the polygon and then you can iterate each of its paths to get the lat and lng values
_getPolygonNewPaths = (polygon) => {
let polygonPaths = []
polygon.getArray().forEach((path, index) => {
const line = {
lat: path.lat(),
lng: path.lng()
}
polygonPaths.push(line)
})
}

@L3V147H4N
Copy link

this adds the listener on every mousedown

@iamgutz
Copy link

iamgutz commented Sep 22, 2016

No, on mouse down it sends the ref of the polygon element that triggered it, with the ref then you can get the polygon position etc.

@tomchentw
Copy link
Owner

Try using polygon.getPath() method with ref?

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

@tomchentw
Copy link
Owner

Please refer to Getting Help section in the README (or #469).

@davidjbradshaw
Copy link

davidjbradshaw commented May 31, 2017

Thank you @iamgutz, that was very helpful. Here is a slightly more up to date way of doing it.

import React, { PureComponent } from 'react';
import propTypes from 'prop-types';
import { Polygon } from 'react-google-maps';

export default class myPolygon extends PureComponent {
  static propTypes = {
    id: propTypes.string.isRequired,
    paths: propTypes.arrayOf(
      propTypes.shape({
        lat: propTypes.number.isRequired,
        lng: propTypes.number.isRequired
      }).isRequired
    ),
    onChangeStart: propTypes.func,
    onChangeEnd: propTypes.func,
    onChangeSet: propTypes.func,
    onChangeInsert: propTypes.func,
    onChangeRemove: propTypes.func,
  }

  static defaultProps = {
    onChangeStart: () => null,
    onChangeEnd: () => null,
    onChangeSet: () => null,
    onChangeInsert: () => null,
    onChangeRemove: () => null,
  }

  shouldComponentUpdate() {
    return false;
  }

  componentDidMount() {
    const addListener = (type, func) => google.maps.event.addListener(this.__polygon, type, func);
    
    addListener('set_at', position => this.props.onChangeSet(this.onChange(position)));
    addListener('insert_at', position => this.props.onChangeInsert(this.onChange(position)));
    addListener('remove_at', position => this.props.onChangeRemove(this.onChange(position)));
  }

  onChange = position => ({
    coordinate: {
      lat: this.__polygon.b[position].lat(),
      lng: this.__polygon.b[position].lng(),
    },
    id: this.props.id,
    position,
  });  

  onRemove = position => ({
    id: this.props.id,
    position,
  });

  __ref = ref => this.__polygon = ref && ref.getPath();

  render() {
    const { paths, onChangeStart, onChangeEnd } = this.props;

    return <Polygon
      ref={this.__ref}
      paths={paths}
      options={{
        editable: true,
      }}
      onMouseDown={onChangeStart}
      onTouchStart={onChangeStart}
      onMouseUp={onChangeEnd}
      onTouchEnd={onChangeEnd}
    />;
  }
}

@vinitsood
Copy link

Hi @zeroasterisk ! Did you manage to resolve this? I am having the same issue right now.

@liutongchen
Copy link

Hi @davidjbradshaw ! Thanks for your answer. I have a question with regards to the update of props.path.

What I'm doing:
I compare this.props.path with nextProps.path in shouldComponentUpdate: if the new path is different from the previous one, shouldComponentUpdate will return true, otherwise, it returns false. The following is a code snippet:

screen shot 2017-11-21 at 5 40 39 pm

Reason for doing this:
I want to update my polygon based on the new props.path by rerendering it but because shouldComponentUpdate always return false, the polygon won't be rendered again.

What is the problem:
This works for me ONLY the first time the user edit the polygon. It seems to me that when shouldComponentUpdate returns false after it returns true the first time, set_at, insert_at and remove_at aren't called.

I'm wondering what did I do wrong that causes this problem? Any help would be appreciated!

@liutongchen
Copy link

liutongchen commented Nov 22, 2017

Hi @davidjbradshaw , I find the problem why ONLY the first time set_at is called. It's because of the way the ref works in react component and also because of the place getPath() is called.
React component's ref takes a callback function that's executed only after the component is mounted and unmounted when it's defined as a bound function, but not when the component is updated. So because getPath() is called in this callback of ref, the event listener of set_at is only added to the initial path Polygon is mounted, but not the path after it's updated. That's why only the set_at is called when shouldComponentUpdate returns true and also the reason set_at gets called every time when shouldComponentUpdate returns false, which is not what I wanted in my case.

Solution:
Based on what I said, I edit the code a bit in order to update Polygon everytime props.path changes:

screen shot 2017-11-23 at 10 34 13 am

@erfoon
Copy link

erfoon commented Jan 22, 2018

Hi,
I don't know if this exact problem was answered or not but I also have problem with updating Polygon while user clicks on map.
I add the location to an array which is passed to Polygon. Like this:

<Map onClick={(event) => {this.props.updatePaths({ lat: event.latLng.lat(), lng: event.latLng.lng() }); }}> <Polygon path={this.props.paths}/> </Map>

The props updates properly but Polygon doesn't. I first had the path as an state in same component but I felt it would work if I update it in parent component and pass it as props, but it didn't fix.

I read this forum and some others but I couldn't find out the answer.

Thank you

@AhmadMayo
Copy link

AhmadMayo commented Mar 6, 2018

if you add a ref to the polygon, you can call .Path() and .Paths from, the ref.
now if a user moves a vertex on the polygon, the handler of mouse up will be called and at that exact moment polygon.getPath() will return the old value. The problem is that the event is called before applying the new coordinates , so if you write the event handler like this

onMouseUpHandler = () => {
   window.setTimeout(() => {
    const newPath = polygon.getPath()
  }, 0);
}

newPath will be the new coordinates, where polygon is reference to the <Polygon /> component
@tomchentw please add this note to the documents. I know that the problem is probably in google's apis, but mentioning this will be very helpful

@Angelk90
Copy link

Angelk90 commented Jan 2, 2020

@davidjbradshaw , @liutongchen :
could you post an example on codesandbox?

@sieder
Copy link

sieder commented Nov 1, 2021

Hi @davidjbradshaw , I find the problem why ONLY the first time set_at is called. It's because of the way the ref works in react component and also because of the place getPath() is called. React component's ref takes a callback function that's executed only after the component is mounted and unmounted when it's defined as a bound function, but not when the component is updated. So because getPath() is called in this callback of ref, the event listener of set_at is only added to the initial path Polygon is mounted, but not the path after it's updated. That's why only the set_at is called when shouldComponentUpdate returns true and also the reason set_at gets called every time when shouldComponentUpdate returns false, which is not what I wanted in my case.

Solution: Based on what I said, I edit the code a bit in order to update Polygon everytime props.path changes:

screen shot 2017-11-23 at 10 34 13 am

@liutongchen

im having this issue now and how can we updated the ref value with hooks? cant seem to get the updated paths after editing the polygon

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