Custom javascript in Esri Survey123 - Part 1


So this week I've been playing with the latest beta release of Esri Survey123; and in particular the ability to now call custom javascript functions though the pulldata() function. This new feature allows you to extend Survey123 quite significantly, such as by using functions to calculate new values or for performing data validation.

So in this post (and a second post to come shortly) I've outlined a couple of common use cases where I've extended Survey123 using javascript functions to calculate new values.

Example 1: Converting Coordinates

One of the frequent challenges with using the ArcGIS Online platform within the UK is that by default all location is stored in WGS 1984 Web Mercator (auxiliary sphere) - EPSG:3857, and accessing location information from the spatial objects is returned either this coordinate system or WGS84 latitude / longitude (EPSG:4326); but a lot of organisations in the UK work to British National Grid (EPSG:27700)

Whilst dropping a pin, or visualising the data within Survey123 on a Web Mercator map is not usually an issue, people often want to be able to get the Easting, Northing grid reference of location. So in this first example I look to use Esri geometry services to take the lat, long of the location of the survey and then use a javascript function to populate separate Easting and Northing fields within my survey.

The javascript 

To call a custom javascript function we first need to create a javascript file. This needs to be placed within a /extensions folder within the survey design folder. 

In this example I created a myFunctions.js file, then within it I then created my custom javascript function projCoords.



I won't go into the detail of the javascript, but the function takes in:

  • a string parameter (geometryServer) - the URL of the geometry service,
  • a location parameter (location) which will be the long, lat of the geopoint captured in the survey,
  • and also a parameter (pCoord)  which will be used to denote whether I want to return the Easting (x) or the Northing (y) of the converted geometry.
The function returns a string value.

Note: the function also takes in a token parameter (useful for if we were working with secured services) although it's not required in this example.

The XLSForm calculation

To call our javascript we do so by using the pulldata() function within the calculation column within the survey XLSForm; for whichever field we want to run the calculation inside. In my survey I have 2 fields; Grid_East and Grid_North; and I am capturing the geopoint survey location in a field called Location.

To calculate Grid _East I enter the following expression in the calculation column:

round(pulldata("@javascript","myFunctions.js","projCoords","https://sampleserver6.arcgisonline.com/arcgis/rest/services/Utilities/Geometry/GeometryServer/project?inSR=4326&outSR=27700&geometries=",pulldata("@geopoint", ${Location}, "x")+"%2C"+pulldata("@geopoint", ${Location}, "y"),"E",pulldata("@Property","token"),true),0)

In my pulldata() expression I'm telling Survey123 that I'm calling javascript, and that it is the myFunctions.js file and the projCoords function within it. Next I'm just passing across values for the parameters that the function is accepting:

geometryServer 
"https://sampleserver6.arcgisonline.com/arcgis/rest/services/Utilities/Geometry/GeometryServer/project?inSR=4326&outSR=27700&geometries="

This is a URL to the geometry service on one of the Esri sample servers; and in this example I'm hard-coding the input spatial reference of 4326 and specifying an output spatial reference of 27700.

location
pulldata("@geopoint", ${Location}, "x")+"%2C"+pulldata("@geopoint", ${Location}, "y")
a concatenated string with both the x (longitude) and y (latitude) obtained by calling the pulldata function on the geopoint object from the Location field, separated with a comma.

pCoord
This is just a string "E", used to tell mu function whether I want to return the Easting or Northing value.

token
pulldata("@Property","token")

debugmode
true

I've also then wrapped the entire outer pulldata() function within a round() function as I don't want to record the coordinates in my form to any decimal places.

For the Grid_North calculation expression I make exactly the same call, but instead pass the string "N" as pCoord.

The demo

So here's what it looks like when I run the survey:



Thoughts & Considerations

There are a couple of gotcha's with using custom javascript functions you need to bear in mind though:

1) Only works on Survey123 (beta) Field App at present
2) Obviously if your JS function calls a REST service then it can only work when your are online
3) Everytime you change the JS you will need to restart Survey123 Connect for ArcGIS (this has caught me out quite a few times!)
4) You cannot use DOM or JS Frameworks within your JS functions
5) You cannot access local files from the JS

Obviously this example is pretty basic; and you could do a lot more to make the javascript function more flexible (e.g. expose more of the underlying REST parameters), but hopefully it's given you a sense for how custom javascript can allow you to pretty quickly make your surveys more powerful.


In the next post I'll show another example (which those of you eagle-eyed enough might have seen in the demo); where we call a custom javascript function to calculate the spatial territory the geopoint is captured in.

Comments

  1. Nicely done! Love it! Thanks for sharing.
    Note that everything you described here will also work with the released version of the software.
    This is an undocumented feature (other than through the Survey123 Early Adopter Community website) and as such not officially supported by Esri, but it was included in the software quite some time ago (early 2018). Again, great post!

    ReplyDelete
  2. This is awesome! I've been trying to get this to work for my workflow but have been unsuccessful up to this point.

    We have field users using the barcode scanner in our first survey. This value is always unique.

    In another survey, I want to reference the previous survey's feature service when the unique barcode is scanned. So data is auto populated based on the unique value.

    Have you used the pull data function for something like the above?

    ReplyDelete

Post a Comment

Popular posts from this blog

Predicting the future

Oracle Spatial 12c - new features for spatial (maybe, possibly, subject to all Oracle caveats)