Experience Builder - My Location Widget - Path Length

343
5
08-07-2025 12:56 PM
ClintonBradley
Emerging Contributor

Hello,

I'm trying to retrieve the length of a path generated by the My Location widget in Experience Builder (standard edition) and report it in a Text widget.

Currently, using statistics within the dynamic content section of the Text widget, I am able to retrieve the Count of locations captured and multiply that by the streaming distance specified, but this isn't overly accurate.

If there's a way to retrieve the path length directly from the geometry using Arcade, I'd love to hear how.

Alternatively, I wouldn't mind being able to retrieve the average speed and start/end time from which I could calculate distance. I appear to have access to these properties in the dynamic content expression window but I cannot perform any calculations with them and the DateDiff function isn't available.

Or similarly, if I could retrieve the lats and longs from each location collected, I think I could also work with that and calculate distance using Arcade.

None of the Arcade Expressions I've attempted to use return any useful information and I can't find much in the way of documentation/examples.

When I return the loadedfeatures or selectedfeatures properties of $datasources in the expression builder it shows me that they return FeatureSets with the following fields: OBJECTID, LineID, location_timestamp, Longitude, Latitude, altitude, Orientation, speed, Accuracy (which is what I see in the popup when clicking on a recorded feature)

But if I return the loadedfields property, it only shows me 0: OBJECTID

I see that $datasources has a layer property that is also supposed to return a FeatureSet but I can't seem to get anywhere with it either.

I see that $datasources has a queryParams dictionary that contains some properties e.g. 'outfields', 'outStatistics', 'returnDistinctValues', 'returnGeometry' that may be helpful but it seems like queryParams is immutable so I'm not sure how to update it.

Hopefully I'm making sense. Any help or references to other resources would be much appreciated!

Thanks

5 Replies
HaydenWelch
MVP Regular Contributor

I'm just gonna throw some code out there to get the ball rolling.

I'm assuming the following:

  1.  You are looking at the data from outside the feature level (e.g. each feature would have access to the $feature object that can be manipulated using Arcade).
  2. That the $datasources['<name>'].loadedfeatures attribute returns a normal FeatureSet of the features in the active view
  3. That you have access to documented Arcade functions that operate on geometry objects
// Grab the features
var features = $datasources['<ds_name>'].loadedfeatures

// Initialize the values you want to calulate
var total_speed = 0
var total_length = 0
var path_count = 0

// Iterate the features and update the totals
for (var feature in features) {
    total_speed += feature['total_speed']
    total_length += LengthGeodetic(feature, 'meters')
    total_paths += 1
}

// Create message components (to be joined later)
var message = [
    `Total Length: ${total_length} meters`,
    `Average Speed: ${total_speed/path_count} m/s`,
    `Total Paths: ${path_count}`
]

// Concatenate the message components and return the string
return Concatenate(message, '\n')

 

This snippet should give you an initial value of 0 for total speed, total length, and feature count. If the loadedfeatures FeatureSet is empty, all of those will return 0. You can capture this state and return something else if you want (just check that path_count > 0 after the for loop).

If the FeatureSet returned is normal, it will be a lazy iterator of Feature objects that can be passed directly to Geometry functions. You can also directly pull the Geometry in json format using Geometry(feature).

LengthGeodetic is the length function you need to use for features that aren't projected and are stored using a Global projection (e.g. WGS84). If you use regular Length, you can get incorrect results.

Hopefully this is somewhat helpful, or will at least give you new fun errors to look at!

ClintonBradley
Emerging Contributor

@HaydenWelch Thank you so much for the reply.

I think my issue is becoming apparent as this isn't working either. Everything returns 0 or NaN. I should have mentioned previously that I've tried looping through the feature sets previously with a counter and the counter always returns 0. The datasource is the output of the My Location widget and in the Text widget, I've only selected the path output when connecting it to data (but I just tried including both path output and locations output with no change). I assume I'm referencing the output properly. 'widget_3_output_trackline-output' (see code below) came from returning $datasources in the arcade editor.

This is the code I'm running now. I tried connecting to the selected features of the output as well and changing the code to use the selectfeatures property but same result. I will continue to research/experiment but if you have any other ideas, let me know.

// Grab the features
var pathfeatures = $datasources['widget_3_output_trackline-output'].loadedfeatures

// Initialize the values you want to calulate
var total_speed = 0
var total_length = 0
var path_count = 0

// Iterate the features and update the totals
for (var pathfeature in pathfeatures) {
    total_speed += pathfeature['total_speed']
    total_length += LengthGeodetic(feature, 'meters')
    path_count += 1
}

// Create message components (to be joined later)
var message = [
    `Total Length: ${total_length} meters`,
    `Average Speed: ${total_speed/path_count} m/s`,
    `Total Paths: ${path_count}`
]

// Concatenate the message components and return the string
return Concatenate(message, '\n')

 

HaydenWelch
MVP Regular Contributor

Have you tried iterating over all the possible attributes of the $dataSources profile variable? (https://developers.arcgis.com/arcade/profiles/experience-builder-widget-formatting/)

 

You might be able to get more from .layer it's not totally clear what the loadedFeatures attribute is exactly. You'd think it would be just the features that are in the visible extent...

ClintonBradley
Emerging Contributor

I can see you going down the same path I did haha. Sorry for not explaining that either. Yes, so the only profile variable available is $datasources and in the absence of any documentation or code snippets (that I can find), the only thing I could do was just start drilling down into what's exposed through $datasources and hope to find the info I need. But that's my issue. Although I can drill down, it seems that no info is ever returned. So it seems to me like the objects themselves are never actually being accessed. The layer property looked promising to me too, along with loadedfeatures and selectedfeatures. I will try .layer again and see if I can get anywhere. And then there's queryparams as well...

One thing that occurred to me over the weekend is I think I can enable manual path tracing (which I assume means I can draw paths on the screen) so I shouldn't have to republish my app and then walk down the hall to collect data to test with haha.

Thanks again for your help. I'll let you know if I figure anything out.

ClintonBradley
Emerging Contributor

I just connected the My Location widget to a table widget and all of the attribute info appears there. So I'm thinking I must not be properly loading the datasource. That would maybe also explain why OBJECTID is the only field listed.

0 Kudos