Pass 'Location' Reliably from Workforce to Survey123

593
2
11-10-2021 09:55 AM
OliverSandoval_p
New Contributor III

Hello,

I am trying to pass location in xy or address format from Workforce to a Survey. I want to be able to populate a text field in Connect with the coordinates or the address and then convert to coordinates, so that I can use it as a parameter for the 'Working with a feature service' Javascript example published by Survey123. 

I want to be able to determine what district the survey is in using that script, it works good on its own, but with Workforce not so much. 

Passing Workforce Location is fine, but in Workforce when you click on the map an xy populates the location, while searching for an address populates the location field in address format. Therefore it cant be expected of end users to consistently submit an assignment with either or. 

I was wondering if anyone had any ideas, I'm thinking there might be a way to calculate a location field in survey123  that accounts for either address or xy but im not sure how to go about it. I am aware of the geocode and reverse geocode functions, but how to account for both formats I'm not sure. I'm new to Connect and super new to Javascript so thank you for any advice. 

 

Here is the script im using;

 

// Query a feature layer and returns a specific field value from 
// the feature that intersects the location
function fieldValueByLocation(layerURL, location, field, token) {
	// Output value.  Initially set to an empty string (XLSForm null)
	let outValue = "";

	// Check to make sure both layerURL and location are provided
	if (layerURL == null || layerURL === "" || location == null || location === "") {
		// The function can't go forward; exit with the empty value
		return outValue;
	}

	// The coordinates will come in as `<lat> <lon> <alt> <acc>`.  
	// We need <lon>,<lat> for the query
	// Note that I'm using the relatively new ` ` string that lets me place variables ${var}
	let coordsArray = location.split(" ");
	let coords = `${coordsArray[1]},${coordsArray[0]}`;
	
	
	// Set up query parameters
	let f = "f=pjson";
	let geometry = `geometry=${coords}`; 
	let geometryType = "geometryType=esriGeometryPoint";
	let inSR = "inSR=4326";
	let spatialRel = "spatialRel=esriSpatialRelIntersects";
	let outFields = `outFields=${field}`;
	let returnGeometry = "returnGeometry=false";
	let returnCount = "returnCount=1";
	let parameters = [f,geometry,geometryType,inSR,spatialRel,outFields,returnGeometry,returnCount].join("&");
	if (token) {
		parameters = parameters + `&token=${token}`;
	}
	let url = `${layerURL}/query?${parameters}`;
	
	/*
	https://services.arcgis.com/P3ePLMYs2RVChkJx/arcgis/rest/services/World_Administrative_Divisions/FeatureServer/0/query?
	f=pjson
	&geometry=-122.32759252280006,47.59698828035203
	&geometryType=esriGeometryPoint
	&inSR=4326
	&spatialRel=esriSpatialRelIntersects
	&outFields=NAME
	&returnGeometry=false
	&returnCount=1
	https://services.arcgis.com/P3ePLMYs2RVChkJx/arcgis/rest/services/World_Administrative_Divisions/FeatureServer/0/query?where=&objectIds=&time=&geometry=-117.19605707130171%2C34.0675386635019&geometryType=esriGeometryPoint&inSR=4326&spatialRel=esriSpatialRelIntersects&resultType=none&distance=0.0&units=esriSRUnit_Meter&returnGeodetic=false&outFields=NAME&returnGeometry=false&returnCentroid=false&featureEncoding=esriDefault&multipatchOption=xyFootprint&maxAllowableOffset=&geometryPrecision=&outSR=&datumTransformation=&applyVCSProjection=false&returnIdsOnly=false&returnUniqueIdsOnly=false&returnCountOnly=false&returnExtentOnly=false&returnQueryGeometry=false&returnDistinctValues=false&cacheHint=false&orderByFields=&groupByFieldsForStatistics=&outStatistics=&having=&resultOffset=&resultRecordCount=&returnZ=false&returnM=false&returnExceededLimitFeatures=true&quantizationParameters=&sqlFormat=none&f=html&token=
	*/
// 	return url;
	// Create the request object
	let xhr = new XMLHttpRequest();
	// Make the request.  Note the 3rd parameter, which makes this a synchronous request
	xhr.open("GET", url, false);
	xhr.send();
	
	// Process the result
	// This an abbreviated version without being able to distinguish different types of errors
	if (xhr.status === 200) {
		let response = JSON.parse(xhr.responseText);
		if (!response.error) {
			if (response.features[0]) {
				outValue = response.features[0].attributes[field];
			}
		}
	}
	return outValue;
}

 

 Here is the form for reference as you see it in the example. 

Surveyform.PNG

Here is the excel that comes with it as well. 

geopointlocationPlease set a location                                 
hiddenadminURLURL for feature layer of 1st level admin boundariesThe URL is added as a hidden question to make the pulldata() function more readable and so that it can be changed outside of the script.https://services.arcgis.com/P3ePLMYs2RVChkJx/arcgis/rest/services/World_Administrative_Divisions/Fea...     null                
noteadminFeatureThe 1st level admin area feature the location is inQueries a feature layer to return the feature the point intersects. Returns a JSON object that can be processed in the form.multiline    pulldata("@javascript", "url_requests.js", "featureByLocation", ${adminURL}, string(${location}))     null100000               
textadminISOISO_CODE valueA specific value can be extracted using the pulldata("@json") function.    pulldata("@json", ${adminFeature}, "attributes.ISO_CODE")                       
textadminNameNAME attributeUses a different function that returns only the text value.    pulldata("@javascript", "url_requests.js", "fieldValueByLocation", ${adminURL}, string(${location}), 'NAME')                     

 

0 Kudos
2 Replies
Jing_Sun
Esri Contributor

Hi, Assuming your workflow is:

(1) In Workforce, click on an assignment point and then click on a button like "Survey at Assignment" to open a Survey123 form.

(2) And in Survey123 you want to get the coordinates of that assignment point and put them into a text field.

Because the integration between Workforce and Survey123 by default passes the coordinates to the opened form (regardless of whether there's a geopoint question or not), we just need to extract the coordinates from the form or the geopoint question.

To confirm the integration is passing the coordinates, you can check the integration URL within the Workforce feature service.

You can refer to the 'Extract geopoint values' section of this page to use the pulldata() function to extract the 'x' and 'y': https://doc.arcgis.com/en/survey123/desktop/create-surveys/geopoints.htm

I hope this will help.

0 Kudos
JoshConrad1
New Contributor III

All:

I have been experiencing the same issues described in this thread: trying to create an attribute expression that calculates lat/long coordinates from a hosted feature layer, then integrate Field Maps with Survey123 to open a form and have the geopoint plot the submitted survey on top of the feature using the result of the attribute expression using a custom URL via the custom URL popup (&center=).

I have been using the "Expression/expr2 - Code to calculate geometry" formula called out in this post (and a multitude of others on the community page) and it was correctly calculating the coordinates in ArcGIS Online Web Viewer Classic, but then when we tested this functionality in the field, the point was not mapping.

I found that the original formula in the "Expression/expr2 - Code to calculate geometry" results in an Array data type, with associated brackets. These brackets do not show up in ArcGIS Online, but when you view the popup in Field Maps, you can see the brackets. So because of this, i tested further and in the original function, i removed the brackets in the result line, which worked but was not perfect. It was not perfect because the coordinate results ended up being truncated to 2 decimals, and even though the submitted form was executing, the point was being plotted hundred of feet away.

After 10 hours of testing and researching these threads (which by the way, all of the contributions are EXPONENTIALLY HELPFUL AND I AM SO GRATEFUL OF YOUR KNOWLEDGE) i was able to find the CORRECT SOLUTION:

1.) Create an attribute expression for latitude:

var lat;
var originShift = 2.0 * PI * 6378137.0 / 2.0;

lat = number(Geometry($feature).y / originShift) * 180.0;
lat = 180.0 / PI * (2.0 * Atan( Exp( lat * PI / 180.0)) - PI / 2.0);
return lat;

2.) Create an attribute expression for longitude:

var lon;
var originShift = 2.0 * PI * 6378137.0 / 2.0;

lon = number(Geometry($feature).x / originShift) * 180.0;
return lon;

3.) Because of the "number" identifier, In ArcGIS Online Web Map Viewer Classic go to Configure Popups, make sure your pop up display is custom, then the important step is to click Configure Attributes. Navigate to the newly created expressions and expand the decimal places to a minimum of 5.

4.) Lastly, in the custom URL make the "&center={expression/expr3},{expression/expr4} where expr 3 is Lat and expr 4 is Long.

I have been testing since i discovered this and it has been running smoothly. Happy Mapping!

0 Kudos