Closed DrBlackBird closed 2 years ago
Ok, I found a solution for that.
In my component which provides the search field I hooked up the above mentioned event listener in my useEffect and set the result value to a state in my parent component.
// Searchfield component
import { useEffect } from 'react';
import { GeoSearchControl, OpenStreetMapProvider } from 'leaflet-geosearch';
import { useMap } from 'react-leaflet';
import 'leaflet-geosearch/dist/geosearch.css';
import Modal from '../Modal';
import { on } from 'events';
const LeafletSearch = ({ setSelectedSearchItem }) => {
const open = true;
const provider = new OpenStreetMapProvider({});
// @ts-ignore
const searchControl = new GeoSearchControl({
provider: provider,
notFoundMessage: 'Could not find location.',
style: 'bar',
showPopUp: false,
showMarker: false,
});
const handleResult = result => {
setSelectedSearchItem(result.location);
};
const map = useMap();
// @ts-ignore
useEffect(() => {
map.addControl(searchControl);
map.on('geosearch/showlocation', handleResult);
return () => map.removeControl(searchControl);
}, []);
return null;
};
export default LeafletSearch;
The parent looks like this
import 'leaflet-defaulticon-compatibility';
import 'leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.css';
import 'leaflet/dist/leaflet.css';
import React, { useEffect } from 'react';
import { MapContainer, Marker, TileLayer } from 'react-leaflet';
import LeafletSearch from '../LeafletSearch';
import Modal from '../Modal';
import { useMap } from 'react-leaflet';
const Map = () => {
const [open, setOpen] = React.useState(false);
const [map, setMap] = React.useState(undefined);
const [selectedSearchItem, setSelectedSearchItem] = React.useState(undefined);
const handleOnClick = () => {
let prevOpen = open;
setOpen(!prevOpen);
};
if (selectedSearchItem) console.log(selectedSearchItem);
return (
<MapContainer
center={[0, 0]}
zoom={14}
scrollWheelZoom={true}
dragging={true}
zoomControl={true}
style={{ height: '100%', width: '100%' }}
whenCreated={map => setMap(map)}>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
/>
{selectedSearchItem && (
<Marker
position={[selectedSearchItem.y, selectedSearchItem.x]}
draggable={true}
eventHandlers={{ click: handleOnClick }}>
<Modal open={open} setOpen={handleOnClick} />
</Marker>
)}
<LeafletSearch setSelectedSearchItem={setSelectedSearchItem} />
</MapContainer>
);
};
export default Map;
Maybe this could be useful to someone who is looking for the same :)
Perfect! Thank you very much for adding the solution. Really appreciated!
Hi all!
First, thanks for your great implementation. It just works and also in a very beautiful way!
I have to need to provide a custom popup. I dont want to use the integrated popup and use a modal or a drawer on the side instead. With react-leaflet I´m able to create an onClick eventhandler on the marker and open a modal on click on of the marker like this:
Is this somehow possible with the implementation or rather not? In the documentation I found this:
this could be somehow what I´m looking for but I dont know how to use it with react-leaflet :(. Maybe somebody could give me a poke into the right direction?
Thanks a lot folks!