Display Info Window on the multiple coordinates on the arcgis map in Next JS
Here below is my next JS Code which is showing a simple ArcGIS map with the points or markers on the specific coordinates.
Can anyone please let me know that how can I display the popup / Info window for the points on the map? e.g. I click on any point and it will open a corresponding popup on it.
import NavBar from '@/components/NavBar'
import axios from 'axios';
import { useRef, useEffect, useState } from 'react';
import { loadModules } from 'esri-loader';
export default function Home({...props}) {
const [state, setState] = useState('');
const MapElement = useRef(null)
const options = {
url: 'https://js.arcgis.com/4.6/',
css: true
};
useEffect(() => {
var vehicleData = props.data
var map, point_symbol;
loadModules([
"esri/views/MapView",
"esri/WebMap",
"esri/Graphic",
"esri/geometry/Point",
"esri/PopupTemplate",
"esri/layers/FeatureLayer","dojo/domReady!"
],options).then(([ MapView, WebMap, Graphic, Point, PopupTemplate, FeatureLayer]) => {
const webmap = new WebMap({
basemap: "gray-vector"
})
var map = new MapView({
map: webmap,
center:[-6.357768833333333, 53.415487166666665],
zoom:6,
container: MapElement.current
})
map.popup.autoOpenEnabled = false;
for(var i=0, i_length=vehicleData.length; i<i_length; i++){
point_symbol = new Point({
longitude:vehicleData[i].longitude,
latitude: vehicleData[i].latitude,
spatialReference: { wkid: 3857 }
})
var template = new PopupTemplate({
title: vehicleData[i].company,
content: vehicleData[i].description
});
var graphic_symbol = new Graphic({
geometry: point_symbol,
symbol: {
type: "simple-marker",
style: "circle",
color: "orange",
size: "18px",
outline: {
color: [150, 200, 255],
width: 5
}
},
popupTemplate: template
});
map.graphics.add(graphic_symbol)
}
map.on("click", function(event) {
map.popup.open({
location: event.mapPoint,
features: [graphic_symbol]
});
});
// map.on("click", function(event) {
// console.log(vehicleData)
// map.popup.open({
// location: event.mapPoint, // location of the click on the view
// title: "You clicked here", // title displayed in the popup
// content: "Your description here" // content displayed in the popup
// });
// });
})
return () => {
if(!!map) {
map.destroy()
map=null
}
}
})
return (
<div id="home-container">
<NavBar />
<div className="app-wrapper" >
<div className="app-content">
<div className="no-padding">
<div className="row gy-4">
<div className="col-12">
<div style={{height:1000, width:1400}} ref={MapElement}></div>
</div>
</div>
</div>
</div>
</div>
</div>
)
}
export async function getServerSideProps(context) {
let response = await axios(process.env.BASE_URL +'/devices/all',{
headers : {
'Authorization' : 'Bearer ' + process.env.TOKEN
}
})
let data = await response.data
return {
props : {
data: data
}
}
}
I need to display pop-up or info window corresponding to each markup multiple circles on the map. In the above code, API call is done by getServerSideProps
, and data as an array of objects is passed to the component using props.
I am able to display multiple circles on the map but don't know how to display info window corresponding to each marker?
Solution 1:
I think that in your code you are having a context problem with the variable i
. When the popup shows the value of i
always gonna be vehicleData.length
.
So you can solve the context problem using let
instead of var
, but I will suggest you another approach.
Declare template
, the popup template, outside the loop, and use two new properties that we will add in the next step.
var template = new PopupTemplate({
title: "{company}",
content: "{description}"
outFields: ["*"],
fieldInfos: [
{ fieldName: "company" },
{ fieldName: "description" }
]
});
Add the information you want to display, to the attributes of the graphics, like this,
var graphic_symbol = new Graphic({
geometry: point_symbol,
symbol: {
type: "simple-marker",
style: "circle",
color: "orange",
size: "18px",
outline: {
color: [150, 200, 255],
width: 5
}
},
popupTemplate: template,
attributes: { // <- here
company: vehicleData[i].company,
description: vehicleData[i].description
}
});
Finally, let the click event search for the graphic, like this,
map.on("click", function(event) {
map.popup.open({
location: event.mapPoint,
fetchFeatures: true
});
});
BTW, I just keep the last step because you change default on purpose, I am not seeing the reason here but you must have one.
Solution 2:
@cabesuon is right. you can remove the on click event and remove map.popup.autoOpenEnabled = false;
too. after that clicking on the graphic will open the popup info by default.
for the table format you may want to use a function for content
// The following snippet shows how to use a function
// to create a simple node and display it in the popup template content
let template = new PopupTemplate({
title: "Population by Gender",
content: setContentInfo
});
function setContentInfo(feature){ // feature here is the graphic, you may access its properties for the table
// create a chart for example
let node = domConstruct.create("div", { innerHTML: "Text Element inside an HTML div element." });
return node;
}