I have a bespoke widget that adds a GeoJson layer to a mapview.
When the map is clicked and features from the GeoJson layer are identified they are loaded back into the widget UI as the list of features selected.
The UI output is made like this:
let message = response.results.length + " Feature selected here.<br \>";
for(let index = 0; index < response.results.length; ++index){
message += "ID: " + response.results[index].graphic.attributes.feature_id + ":<br \>";
message += "Date: " + response.results[index].graphic.attributes.date_time + "<br \>";
message += '<Button onClick="getDetails(\'' + response.results[index].mapPoint.latitude.toFixed(4) + ', ' + response.results[index].mapPoint.longitude.toFixed(4))" size="default">Load</Button>';
}
All this loads into the UI fine but the scope on the button onClick fails with this message:
Uncaught ReferenceError: getDetails is not defined
at HTMLButtonElement.onclick (0/?draft=true:1:1)
onclick @ 0/?draft=true:1
Sorry but lost as to how I can get scope back on the button click, tried so many approaches and just more confused now.
Is this a functional component or a class component?
If its a class component, you could try:
message += '<Button onClick="this.getDetails(\'' + response.results[index].mapPoint.latitude.toFixed(4) + ', ' + response.results[index].mapPoint.longitude.toFixed(4))" size="default">Load</Button>';
Otherwise you can try:
message += '<Button onClick="(e) => getDetails(\'' + response.results[index].mapPoint.latitude.toFixed(4) + ', ' + response.results[index].mapPoint.longitude.toFixed(4))" size="default">Load</Button>';
One of those might work.
Its a functional component and the error is gone on button click, so thanks for that bit.
Unfortunately the function getDetails is not executing it seems as I've stripped it down to just output a console.log and no output on click, but no error either.
Will poke about some more to understand.
The function being called currently only look like this:
const getDetails = (clickPointLat, clickPointLon) => {
console.log("In getDetails");
}
Below is relevant code, hopefully its enough as I think the logic it defines is whats got me.
Definitely react naive issue as not my standard framework as you'll see by the 'cheating' using jQuery to manage div updates!!!
Happy to rework all if pointers/advice possible so thanks for help so far!!
layer in below code is a geoJsonLayer of polylines added at the start of the code.
const activeViewChangeHandler = (jmv: JimuMapView) => {
if (jmv) {
setJimuMapView(jmv);
/*************MAP CLICK - START****************
* When the map is clicked get map coodinates.
*/
jmv.view.on("click", tracksLayerClickHandler);
function tracksLayerClickHandler(event){
//only include graphics from Tracks Layer
const opts = {
include: layer
};
jmv.view.hitTest(event, opts).then(tracksLayerFeatureHandler);
};
function tracksLayerFeatureHandler(response){
if (response.results.length == 1){
/*Response Attributes include:
date_time: "2022-07-20 13:00:00+00"
feature_id: int
title: string
*/
let message = `Getting Details for feature: ${response.results[0].graphic.attributes.feature_id}<br \>
Date: ${new Date(response.results[0].graphic.attributes.date_time).toLocaleDateString()}<br \>
Title: ${response.results[0].graphic.attributes.title}
`;
$('#trackList').html(message);
getDetails(response.results[0].graphic.attributes.feature_id, response.results[0].mapPoint.latitude.toFixed(4), response.results[0].mapPoint.longitude.toFixed(4));
}else{
let message = response.results.length + " Features here.<br \>";
for(let index = 0; index < response.results.length; ++index){
message += "Feature: " + response.results[index].graphic.attributes.feature_id + ":<br \>";
message += "Date: " + new Date(response.results[index].graphic.attributes.date_time).toLocaleDateString() + "<br \>";
message += "Title: " + response.results[index].graphic.attributes.title;
message += '<Button onClick="(e) => getDetails(\'' + response.results[index].graphic.attributes.feature_id + '\', ' + response.results[index].mapPoint.latitude.toFixed(4) + ', ' + response.results[index].mapPoint.longitude.toFixed(4) + ')" size="default">Get Details</Button><hr />';
}
$('#trackList').html(message);
}
};
/*************MAP CLICK - END****************/
}
}
const getDetails = (featureID, clickPointLat, clickPointLon) => {
console.log("In getDetails");
//Can use esriRequest now to make external API call for feature details
//API request results will then be loaded into the featureDetails div!!!
//This works fine where the click result is only 1 feature.
//Can't reach this method from the button created from a multi-feature response.
}
return (
<div className="widget-starter jimu-widget" style={{ overflow: 'auto', display: 'flex', flexWrap: 'wrap', justifyContent: 'center'}}>
{ props.useMapWidgetIds && props.useMapWidgetIds.length === 1 && ( <JimuMapViewComponent useMapWidgetId={props.useMapWidgetIds?.[0]} onActiveViewChange={activeViewChangeHandler}/> )}
<div id="trackList">
No Track Features Selected.
</div>
<div id="featureDetails">
No Feature Details.
</div>
</div>
);