Hi!
I am having a hard time figuring out arcade expression to work within my dashboard. I also don't fully know if it is even possible to do within dashboards. Anyway....
I have a dashboard that is connect to a Survey123. The survey contains a multiple select question, which I learned is saved as csv, so I found an expression to split out the answers from the multiple select question. The issue is I now need to connect this new feature set dictionary to the existing feature layer within the webmap. So, I created a join expression, but I keep getting and can't figure out how to correct:
Expected "'", "(", "+", "-", "@", "CASE", "DATE", "EXTRACT", "FALSE", "INTERVAL", "N'", "NULL", "POSITION", "SUBSTRING", "TIMESTAMP", "TRIM", "TRUE", "`", [ \t\n\r], [0-9], or [A-Za-z_\x80-] but "$" found.
The end goal is that someone can search by specific rent amount and see what locations offer that rent amount.
Dashboard below
https://dgco.maps.arcgis.com/apps/dashboards/2df513c195bb4560b61145f4064484dd
Expression below
// Reference layer using the FeatureSetByPortalItem() function.
var fs = FeatureSetByPortalItem(Portal('https://www.arcgis.com'), '288db7f54ea048c5b6241f156ef0f646' , 0, ['*'], true);
// Empty dictionary to capture each rental amount reported as separate rows.
var choicesDict = {'fields': [{ 'name': 'split_choices', 'type': 'esriFieldTypeString'}],
'geometryType': 'esriGeometryPoint', 'features': []};
var index = 0;
// Split comma separated Rental Amountss and store in dictionary.
for (var feature in fs) {
var split_array = Split(feature["rent_amount"], ',')
var count_arr = Count(split_array)
for(var i = 0; i < count_arr; i++ ){
choicesDict.features[index++] = {
'attributes': { 'split_choices': Trim(split_array[i]),
}}
}}
// Convert dictionary to featureSet.
var fs_dict = FeatureSet(Text(choicesDict));
GroupBy(fs_dict, ['split_choices'],
[{ name: 'split_count', expression: 'split_choices', statistic: 'COUNT' }]);
var joinedDict = {
fields: [
{ name: "split_choices", type: "esriFieldTypeString" },
{ name: "address", type: "esriFieldTypeString" },
{ name: "landlord", type: "esriFieldTypeString" },
],
geometryType: "esriGeometryPoint",
'features':[]};
var i = 0;
for (var t in fs_dict) {
var fsid = t["split_choices"]
for (var p in Filter(fs, "SplitChoices = "+fsID)){
joinedDict.features[i] = {
attributes: {
SplitChoices: fsID,
Address: p["address"],
Landlord: t["landlord"],
},
geometry: Geometry(p)
}
}
i++
}
return FeatureSet(Text(joinedDict));
If there is better way for handling this issue, let me know!
Thanks
Scout
Solved! Go to Solution.
Your expression fails in line 37.
fsID is "$1000-$1100". The sql query you're constructing is "SplitChoices = $1000-$1100".
This is an invalid query, you need "SplitChoices = '$1000-$1100'", note the single quotes.
You could use the @ notation, that will handle the field type for you:
"SplitChoices = @fsID"
Or you could do it yourself with template literals:
`SplitChoices = '${fsID}'`
But even then this line won't work, because you're either trying to filter the wrong featureset, or you use the wrong query. fs doesn't have a field SplitChoices, and if you want to query rent_amount, you should use LIKE:
`rent_amount LIKE '%${fsID}%'`
Also, GroupBy doesn't change the input featureset, but returns a new one, so you have to store the result in a variable (line 22).
I couldn't really make sense of your attempted join, but I think you are trying to achieve something like this:
// Reference layer using the FeatureSetByPortalItem() function.
var fs = FeatureSetByPortalItem(Portal('https://www.arcgis.com'), '288db7f54ea048c5b6241f156ef0f646' , 0, ['*'], true);
var outputDict = {
fields: [
{ name: "rent_amount", type: "esriFieldTypeString" },
{ name: "address", type: "esriFieldTypeString" },
{ name: "landlord", type: "esriFieldTypeString" },
],
geometryType: "esriGeometryPoint",
features: []};
var i = 0;
// iterate over the input features
for (var f in fs) {
// split the rent field
var rentSplit = Split(f["rent_amount"], ",")
// iterate over the rent amounts
for(var r in rentSplit) {
// append a new output feature with the input feature's attributes and the current rent amount
outputDict.features[i++] = {
attributes: {
rent_amount: rentSplit[r],
address: f["address"],
landlord: f["landlord"]
},
geometry: Geometry(f)
}
}
}
return FeatureSet(Text(outputDict));
The problem is that the Dashboard can only filter by equality: rental_amount_layer = rental_amount_selector
But if you select "$500-$600", the dashboard can't find features to show, because the values in the layer are built like "$500-$600,$600-$800,$1000-$1100".
What you need is a LIKE filter, which doesn't seem to exist in Dashboard.
So, you've got (at least) two options:
If you have to use Dashboard, you need to reconfigure your layer to only show the separate rental amounts (many points at the same location). This way, you can even skip the data expression and build the category selector based on the layer.
If you don't have to use Dashboard, you can easily achieve this with an Experience. Add your map and a Filter widget, set the filter query to "Rent Amount - includes - predefined values", and define some categories.
And then you can select the amounts you want to filter:
Your expression fails in line 37.
fsID is "$1000-$1100". The sql query you're constructing is "SplitChoices = $1000-$1100".
This is an invalid query, you need "SplitChoices = '$1000-$1100'", note the single quotes.
You could use the @ notation, that will handle the field type for you:
"SplitChoices = @fsID"
Or you could do it yourself with template literals:
`SplitChoices = '${fsID}'`
But even then this line won't work, because you're either trying to filter the wrong featureset, or you use the wrong query. fs doesn't have a field SplitChoices, and if you want to query rent_amount, you should use LIKE:
`rent_amount LIKE '%${fsID}%'`
Also, GroupBy doesn't change the input featureset, but returns a new one, so you have to store the result in a variable (line 22).
I couldn't really make sense of your attempted join, but I think you are trying to achieve something like this:
// Reference layer using the FeatureSetByPortalItem() function.
var fs = FeatureSetByPortalItem(Portal('https://www.arcgis.com'), '288db7f54ea048c5b6241f156ef0f646' , 0, ['*'], true);
var outputDict = {
fields: [
{ name: "rent_amount", type: "esriFieldTypeString" },
{ name: "address", type: "esriFieldTypeString" },
{ name: "landlord", type: "esriFieldTypeString" },
],
geometryType: "esriGeometryPoint",
features: []};
var i = 0;
// iterate over the input features
for (var f in fs) {
// split the rent field
var rentSplit = Split(f["rent_amount"], ",")
// iterate over the rent amounts
for(var r in rentSplit) {
// append a new output feature with the input feature's attributes and the current rent amount
outputDict.features[i++] = {
attributes: {
rent_amount: rentSplit[r],
address: f["address"],
landlord: f["landlord"]
},
geometry: Geometry(f)
}
}
}
return FeatureSet(Text(outputDict));
Yes! That is exactly what I was trying to go for! Much appreciation 😁 and thank you for helping me understand the expression!
Hey Johannes!
Another question... I am using category select widget within my dashboard using this expression. The issue is I want to have only one option instead of multiple options with same answer. Such as, currently there are three options for $500-$600. Instead, I want there to be one option $500-$600 and then the other widgets filter out those rentals containing option $500-$600 within dashboard. Do you know if this is possible to do?
Inside the category filter, don't use the "Features" option. You need the "Grouped Values" option and group by rent_amount, which should give you distinct values.
I tried doing it by "Grouped Values". However, when I do that it doesn't work with the geometry within the map or the other widgets. And it doesn't save my actions for filters. The image below is what it looks like after I reopen the widget to see if it saved my active targets. So how do I get it to filter the map and other widgets? or is this a bug?
The problem is that the Dashboard can only filter by equality: rental_amount_layer = rental_amount_selector
But if you select "$500-$600", the dashboard can't find features to show, because the values in the layer are built like "$500-$600,$600-$800,$1000-$1100".
What you need is a LIKE filter, which doesn't seem to exist in Dashboard.
So, you've got (at least) two options:
If you have to use Dashboard, you need to reconfigure your layer to only show the separate rental amounts (many points at the same location). This way, you can even skip the data expression and build the category selector based on the layer.
If you don't have to use Dashboard, you can easily achieve this with an Experience. Add your map and a Filter widget, set the filter query to "Rent Amount - includes - predefined values", and define some categories.
And then you can select the amounts you want to filter:
Hello @JohannesLindner! This is a delayed response, but I wanted to reach out as you know a lot about dashboards and advanced calculations. I have something similar where I have a lot of output fields in the dictionary because I need to use them for filtering these calculated attributes. However, upkeep of that can be difficult and I was wondering if there was a simpler way that you know of to output all fields automatically in a dictionary to then be used as the output feature set. Usually what I am doing is calculating one field that is used as the indicator element, and all other output fields are there for the common key when filter actions are applied.
Ah okay, thanks for sharing! I think I will try to go the experience builder route. I really appreciate the help with this!