Select to view content in your preferred language

Editing Data Expressions for List view in Dashboards

531
8
Jump to solution
02-21-2025 01:38 AM
DeboMallick
Emerging Contributor

Hi . I am trying to understand how to build a data expression for a list view in a dashboard where the output of two geometric expressions should pupulate into a FeatureSet. I am creating a buffer and intersect between two layers and if the condition satisfies, the output should return a text value within the FeatureSet.

This works while configuring pop ups but do not know how to populate this for a list view with dashboards.

Scripts looks something like this while configuring pop ups. 

var fs1 = FeatureSetByPortalItem(Portal('PortalURL',0,['Event','Severity'],false); #polygon layer
var fs2 = FeatureSetByPortalItem(Portal('PortalURL',0,['Name','City'],false); #point layer
 
var b1 = Buffer(fs2, 10, 'miles')

var int1 = First(Intersects(fs1, b1))
 

if(!IsEmpty(int1)) {
return Proper(`Affected by ${int1.Event}.`)

}  

else {
return "Not affected by Event"
}

How would I show this output on a FeatureSet. Is this possible here?

 
0 Kudos
1 Solution

Accepted Solutions
NicoleJohnson
Frequent Contributor

I see a "First" at the top of your code (which means you're working with one feature) and I'm not sure what the intention is there. That would be useful if you wanted to take the first feature in a featureset, but you'll need to go through all your features if I'm understanding correctly.

I would also create something (like a dictionary) to hold the output before you start "creating" the output (doing the intersection), if that makes sense? I also don't think you need all those Text functions in Push if those are already strings?

Also, you show the results of your code which does have the "status" field, but I think in the next screenshot (your dashboard list), you're wondering why you're only seeing the census tract name? That would be down to how your list is formatted, not the code. 

Here's an example of what I think you're trying to do, but with the Living Atlas current wildfires layer and the ACS population layer. For each state, I want to list the wildfires that affect that state:

 

// Get source featuresets
var wildfiresFS = FeatureSetByPortalItem(Portal('https://www.arcgis.com'), 'd957997ccee7408287a963600a77f61f', 1, ['IncidentName'], true)
var stateFS = FeatureSetByPortalItem(Portal('https://www.arcgis.com'), 'f430d25bf03744edbb1579e18c4bf6b8', 0, ['Name'], true)

// Create a dictionary for the output
var outputDict = {fields: [
{name: 'StateName', type: 'esriFieldTypeString'},
{name: 'IncidentsName', type: 'esriFieldTypeString'}],
geometryType: '',
features: []
}

// Loop through each state and see if it's affected by any wildfires
for (var i in stateFS){
  
  // Create variables to hold the name of the wildfire(s) and how long the name is, since I'll need to tidy that up later
  var wildfiresTxt
  var wildfiresTxtCount

  // Loop through each fire, and if it affects the state, list it
  for (var fire in wildfiresFS){
    if (Intersects(fire, i)){
      wildfiresTxt += fire.IncidentName + ", "
      wildfiresTxtCount = Count(wildfiresTxt)
    }
  }

  // Write results
  Push(outputDict['features'], {attributes: {StateName: i.Name, IncidentsName: Left(wildfiresTxt, wildfiresTxtCount-2)}})
}

var fsNew = FeatureSet(Text(outputDict))

return fsNew

 

 

Here's the result (Arizona is a little weird because at the moment there's one fire without a name, and I'd rather the states without fires just be null, but this is just an example):

NicoleJohnson_0-1740578542845.png

Here's where you can add more fields to your list presentation:

NicoleJohnson_0-1740579659492.png

 

View solution in original post

8 Replies
AndreasHall
Esri Regular Contributor

FeatureSetByPortalItem is not supported in Dashboards lists. Only the Core function bundle is supported (Dashboard List Formatting | ArcGIS Arcade | Esri Developer)

0 Kudos
DeboMallick
Emerging Contributor

Hi @AndreasHall . Seems that it is supported. 

In case of something like this

var fs1 = FeatureSetByPortalItem(Portal('PortalURL',0,['Event','Severity'],false); #polygon layer
 
return fs1;
 
I am able to see the features populated within the list view.
0 Kudos
DeboMallick
Emerging Contributor

And example would be (using a living atlas layer here)

var fs1FeatureSetByPortalItem(Portal('https://www.arcgis.com'),'a6134ae01aad44c499d12feec782b386',6,['Event', 'Severity','Certainty', 'Summary','Updated', 'Start', 'End_'], false);
 
return fs1;
0 Kudos
AndreasHall
Esri Regular Contributor

Okay, I might be wrong. Arcade is not my field of expertise.

NicoleJohnson
Frequent Contributor

I think the problem/difference is that for your pop-ups, what's being returned is the result for one feature, whereas for your list, you need the whole featureset, so you need to store your results in a new featureset and return that featureset. You can use a dictionary to do this. The example shows a lot of options, but you don't need to actually set all those up. The basic way is to just set up your fields (in this case, I didn't need geometry):

var newDict = {fields: [
{name: 'NAME', type: 'esriFieldTypeString'},
{name: 'CENSUS0', type: 'esriFieldTypeInteger'},
{name: 'CENSUS1', type: 'esriFieldTypeInteger'},
{name: 'REGION', type: 'esriFieldTypeString'}],
geometryType: '',
features: []
}

After you create this, loop through the featureset(s) that are going to populate your new featureset. In this (heavily abbreviated) example, I wanted to add a "region" field to some ACS data on Living Atlas. This would be where your "affected by event"/"not affected by event" stuff goes:

for (var i in fsMI){ // This is the featureset I'm starting with, that doesn't have all the fields I need

  var region

  When(
    i.NAME=="esrdfgbtdgbfd", region = '1',
    i.NAME=="seihfirkesj", region = '8',
    region = '0'
    )
  // Now that I have my regions, I can take the dictionary I created earlier and use it to fill my new featureset
  Push(newDict['features'], {attributes: {NAME: i.NAME, CENSUS0: i[censusField0], CENSUS1: i[censusField1], REGION: region}})
}

var fsMINew = FeatureSet(Text(newDict))
DeboMallick
Emerging Contributor

Thanks for looking into this. Unfortunatly I am still not very clear on how to implement the dictionary function. 

For example the first part of my code would run the geometric/spatial operation

 

 

var fs1 = FeatureSetByPortalItem(Portal('https://www.arcgis.com'),'a6134ae01aad44c499d12feec782b386',6,['Event', 'Severity','Certainty', 'Summary','Updated', 'Start', 'End_'],false); //polygon layer
var fs2 = FeatureSetByPortalItem(Portal('https://www.arcgis.com'),'f430d25bf03744edbb1579e18c4bf6b8',2,['Name', 'State','County', 'B01001_001E'],false); //polygon layer

var int1 = First(Intersects(fs1, fs2))

 

 

In my next step I will have to declare the fields I will be using to update the output by building a dictionary from the second ACS feature service (fs2). In this case I have delcared a new field named STATUS (as you had defined Region) to show the "Affected by/not Affected by " statement.

 

 

var newDict = {fields: [
{name: 'NAME', type: 'esriFieldTypeString'},
{name: 'STATE', type: 'esriFieldTypeString'},
{name: 'COUNTY', type: 'esriFieldTypeString'},
{name: 'STATUS', type: 'esriFieldTypeString'}],
geometryType: '',
features: []
}

 

 

Now I shall have to loop through the featureset(s) and populate the new featureset. In this case I wanted to use the output of the intersect operation. I used the When function but could I stick to an if else loop?

 

 

for (var i in fs2){ 

  var status

  When(
    !IsEmpty(int1), status = `Affected by ${int1.Event}.`,
    IsEmpty(int1), status = `Not Affected.`
    )
  Push(newDict['features'], {attributes: {NAME: i.NAME, STATE: i.STATE, COUNTY: i.COUNTY, STATUS: status}})
}
var fs2New = FeatureSet(Text(newDict))

 

 

In this case I do get an error while writing the When function.

I did also use something like this 

 

for (var i in fs2){ 

  var status

  When(
    i.STATE=="Alabama", status = `Affected by ${int1.Event}.`,
    i.STATE=="Alaska", status = `Affected by ${int1.Event}.`,
    status = `Not Affected.`
)
  Push(newDict['features'], {attributes: {NAME: i.NAME, STATE: i.STATE, COUNTY: i.COUNTY, STATUS: status}})
}

var fs2New = FeatureSet(Text(newDict))

return fs2New

 

In this case it asks me to verify my test data. I am using both livingatlas layers in this case.

I also did explore the case of adding the When conditions as an expression as outlined within the Distinct function of the FeatureSet.

e.g.
Distinct($layer, { name: "Density", expression: "CASE WHEN PopDensity < 100 THEN 'Low' WHEN PopDensity >= 100 THEN 'High' ELSE 'N/A' END" })

Thanks again for all your help. I think we're very close and I am making a mistake due to my lack of knowledge on featuresets.

0 Kudos
DeboMallick
Emerging Contributor

I also did try another approach. Seemed a bit clearer to me and it also does provide an output but just one record.

 

 

var fields1= ['Event', 'Severity','Certainty', 'Summary','Updated', 'Start', 'End_'];
var fields2= ['Name', 'State','County'];
var fs1 = FeatureSetByPortalItem(Portal('https://www.arcgis.com'),'a6134ae01aad44c499d12feec782b386',6,fields1,false); //polygon layer
var fs2 = FeatureSetByPortalItem(Portal('https://www.arcgis.com'),'f430d25bf03744edbb1579e18c4bf6b8',2,fields2,false); //polygon layer
//Ran the intersect 
var int1 = First(Intersects(fs1, fs2))

var features =[];
//looping through intersect condition
for (var f in fs2) {
   var i = First(Intersects(fs1, f)) 

    if (!IsEmpty(i)) {
      var status = `Affected by ${int1.Event}.`
    } else {
      status = `Not Affected.`
    }
  }
  Push(features, 
  { 
    attributes: 
    {
      Name: Text(f["Name"]),
      State: Text(f["State"]),
      County: Text(f["County"]),
      status: Text(status) 
    }
  });

//creating an output table
var table = {
  'fields' :[
    {
      name: "Name",
      alias: "Name",
      type: "esriFieldTypeString"
    },
     {
      name: "State",
      alias: "State",
      type: "esriFieldTypeString"
    },
    {
      name: "County",
      alias: "County",
      type: "esriFieldTypeString"
    },
    {
      name: "status",
      alias: "status",
      type: "esriFieldTypeString"
    },

  ],
  geometryType: "",
  features: features
}

return FeatureSet(table);

 

 

Output:

DeboMallick_1-1740495111212.png

 


Unfortunatly I get only one record with a single FID.

DeboMallick_0-1740495085595.png

 


Should'nt I be getting all the records within the ACS county layer. Would be great if you could help with the loop

0 Kudos
NicoleJohnson
Frequent Contributor

I see a "First" at the top of your code (which means you're working with one feature) and I'm not sure what the intention is there. That would be useful if you wanted to take the first feature in a featureset, but you'll need to go through all your features if I'm understanding correctly.

I would also create something (like a dictionary) to hold the output before you start "creating" the output (doing the intersection), if that makes sense? I also don't think you need all those Text functions in Push if those are already strings?

Also, you show the results of your code which does have the "status" field, but I think in the next screenshot (your dashboard list), you're wondering why you're only seeing the census tract name? That would be down to how your list is formatted, not the code. 

Here's an example of what I think you're trying to do, but with the Living Atlas current wildfires layer and the ACS population layer. For each state, I want to list the wildfires that affect that state:

 

// Get source featuresets
var wildfiresFS = FeatureSetByPortalItem(Portal('https://www.arcgis.com'), 'd957997ccee7408287a963600a77f61f', 1, ['IncidentName'], true)
var stateFS = FeatureSetByPortalItem(Portal('https://www.arcgis.com'), 'f430d25bf03744edbb1579e18c4bf6b8', 0, ['Name'], true)

// Create a dictionary for the output
var outputDict = {fields: [
{name: 'StateName', type: 'esriFieldTypeString'},
{name: 'IncidentsName', type: 'esriFieldTypeString'}],
geometryType: '',
features: []
}

// Loop through each state and see if it's affected by any wildfires
for (var i in stateFS){
  
  // Create variables to hold the name of the wildfire(s) and how long the name is, since I'll need to tidy that up later
  var wildfiresTxt
  var wildfiresTxtCount

  // Loop through each fire, and if it affects the state, list it
  for (var fire in wildfiresFS){
    if (Intersects(fire, i)){
      wildfiresTxt += fire.IncidentName + ", "
      wildfiresTxtCount = Count(wildfiresTxt)
    }
  }

  // Write results
  Push(outputDict['features'], {attributes: {StateName: i.Name, IncidentsName: Left(wildfiresTxt, wildfiresTxtCount-2)}})
}

var fsNew = FeatureSet(Text(outputDict))

return fsNew

 

 

Here's the result (Arizona is a little weird because at the moment there's one fire without a name, and I'd rather the states without fires just be null, but this is just an example):

NicoleJohnson_0-1740578542845.png

Here's where you can add more fields to your list presentation:

NicoleJohnson_0-1740579659492.png