Select to view content in your preferred language

Using data expressions in the advanced formatting of an element to calculate area

798
3
01-09-2023 03:44 PM
JasmineSpring
Occasional Contributor

Hello

I was wondering if the following possible. I have a point dataset that gets updated regularly that I want to use in my dashboard. I would like the user to be able to select a time period and then the indicator automatically calculate a buffer and display the area result in my element. Is this something that can be added in the advanced formatting section of the element?

0 Kudos
3 Replies
JohannesLindner
MVP Frequent Contributor

It can be done, but not in the advanced formatting. In there, you can only access the current datapoint, you can't load featuresets.

Instead, you need to calculate the buffers in a data expression, use that expression as input for your indicator, and then filter the indicator's data source using user supplied values.

 

So, doing this step by step:

  • Add an indicator
    JohannesLindner_0-1673344640025.png

     

  • Create a new data expression for it
    JohannesLindner_1-1673344718129.png
// load your points
var p = Portal("https://xxx/portal/")
var id = "abc"
var sublayer = 1
var date_field = "Zeitstempel"
var layer = FeaturesetByPortalItem(p, id, sublayer, [date_field], true)

// define the output
var output_dict = {
    geometryType: "",
    fields: [
        {name: "DateField", type: "esriFieldTypeDate"},
        {name: "BufferArea", type: "esriFieldTypeDouble"}
        ],
        features: []
}

// create the buffers
for(var f in layer) {
    var new_f = {attributes: {
        DateField: Number(f[date_field]),
        BufferArea: Area(Buffer(f, 10, "meters"), "square-meters")
    }}
    Push(output_dict.features, new_f)
}

// return the featureset
return Featureset(Text(output_dict))

 

  • Change the indicator's parameters:
    • show the sum of the BufferArea field
    • add some text
  • Add a top or side bar
    JohannesLindner_2-1673345300621.png

     

  • Add a date selector to the bar
    JohannesLindner_3-1673345350283.png

     

  • Change these two parameters:
    JohannesLindner_4-1673345465215.png

     

  • Add an action: Filter the indicator's date field
    JohannesLindner_5-1673345519187.png

     

Now the user-selected date range filters the indicator's data source:

JohannesLindner_9-1673345813653.png

 

JohannesLindner_8-1673345773904.png

 


Have a great day!
Johannes
JasmineSpring
Occasional Contributor

Hi Johannes

 

Thank you so much!!  The reason why I was seeing if there was a way to process the data after the date selection is that I dont need the sum of the buffered points. I need to be able to union after the date selection to get an area calculation without any overlap. Sorry I should have added that information. You help is very much appreciated 🙂

0 Kudos
JohannesLindner
MVP Frequent Contributor

Ah. As far as I know, there's no way to do that dynamically.

 

Only way I can think of is to have statically defined periods. So your users wouldn't be able to filter for "every point between these two arbitrary dates", only for "every point that falls into this predefined period".

To do this, you can use this data expression:

 

// load your points
var p = Portal("https://xxx/portal/")
var id = "abc"
var sublayer = 1
var date_field = "Zeitstempel"
var layer = FeaturesetByPortalItem(p, id, sublayer, [date_field], true)

// define the output
var output_dict = {
    geometryType: "",
    fields: [
        {name: "Period", type: "esriFieldTypeString"},
        {name: "TotalArea", type: "esriFieldTypeDouble"},
        ],
        features: []
}

// define the periods as dictionary {period_name: [start, end]}
// The Union() function below takes a lot of time, so don't use too many periods!
var periods = {
    "2020": [Date(2020, 0, 1), Date(2020, 11, 31)],
    "2021": [Date(2021, 0, 1), Date(2021, 11, 31)],
    "2022": [Date(2022, 0, 1), Date(2022, 11, 31)],
    "2023": [Date(2023, 0, 1), Date(2023, 11, 31)],
    "2020 - Q1": [Date(2020, 0, 1), Date(2020, 2, 31)],
    "2020 - Q2": [Date(2020, 3, 1), Date(2020, 5, 30)],
    "2020 - Q3": [Date(2020, 6, 1), Date(2020, 8, 30)],
    "2020 - Q4": [Date(2020, 9, 1), Date(2020, 11, 31)],
}

// loop over the periods
for(var p in periods) {
    // filter your points
    var start = periods[p][0]
    var end = periods[p][1]
    var sql = `${date_field} >= @start AND ${date_field} <= @end`
    var filtered_layer = Filter(layer, sql)
    // buffer each point
    var buffers = []
    for(var f in filtered_layer) {
        Push(buffers, Buffer(f, 10, "meters"))
    }
    // union all buffers
    var unioned_buffers = Union(buffers)
    // write new feature
    var new_f = {attributes:{
      Period: p,
      TotalArea: Area(unioned_buffers, "square-meters")
    }}
    Push(output_dict.features, new_f)
}

// return the featureset
return Featureset(Text(output_dict))

 

 

Set the indicator's value to Sum of TotalArea.

Instead of the date selector, use a category selector. Use your period names as categories.

JohannesLindner_0-1673430643359.png

 

As action, filter the indicator's Period field.

 

 

Now your users can filter by the periods you defined and get the unioned areas.

JohannesLindner_1-1673430765325.png

 

JohannesLindner_2-1673430796273.png

 


Have a great day!
Johannes