Access bespoke Widget click events

354
5
11-24-2023 08:35 AM
Labels (1)
diplonics
New Contributor II

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.

0 Kudos
5 Replies
Grant-S-Carroll
Esri Contributor

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.

0 Kudos
diplonics
New Contributor II

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.

 

0 Kudos
diplonics
New Contributor II

The function being called currently only look like this:

 

const getDetails = (clickPointLat, clickPointLon) => {
	console.log("In getDetails");
}
0 Kudos
Grant-S-Carroll
Esri Contributor
The part where you build the button, it looks like it’s the result of a call to a service. Can you show the full code for that please?
0 Kudos
diplonics
New Contributor II

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>
);

 

0 Kudos