I have features with calculated expressions that take values from nearby points and produce a shared final score. The issue I am facing is that when an additional point is created or one point is edited, all the other points need to be selected individually to be updated. In the picture below, there are four black points for each leg of an intersection. After each point is created and their forms are completed, the user has to go back and click each point individually to reupdate each point once again. Since any change to one point affects all 4.
I am wondering if there is a way to add to the arcade code to automatically update. Or any other workarounds that would solve this problem.
Solved! Go to Solution.
Please post code as a code snippet:
for (var feat in matchingProj){
if (IsNull(feat.LegDirection)){
continue
}
var sumDenominator = 0;
for (var field in fieldsAndScores) {
if (!IsEmpty(feat[field])) {
sumDenominator += fieldsAndScores[field];
}
}
totalSumDenominator += sumDenominator;
}
What you want to do is get all the OIDs or GlobalID of the features you want to update. You are looping over them, so store them into a list/array.
When done, convert that list into a list of dictionaries, with the globalid and an attributes keyword, with the field you wish to update in it
Since this is an attribute rule, it always fires in the database, so it will work no matter what client does the edits. Some client are not aware of the return edit payload from apply edits(instead of the edit just returning success, it returns the others features that were edited so it can do a refresh). So if the client is not reading the return edits, you just need to refresh to see the other updates.
The return edit statement you want is the Updates:
return {
'edit': [{
'className': 'b_edit_dict',
'updates': [{
'globalID': '{7EBAB596-E9DB-40D8-9756-B2EBED2500B7}',
'attributes': {
'field_name': 22
}
}]
}]
}
Using an attribute rule, yes you can. You can find all points in a distance and trigger an edit on that feature, so its attribute rule fire or calculate the value and set it on that feature.
You want to look at the return edits keywords:
Hi Mike, thank you very much for pointing me in the right direction.
Looks like I need to use the example in the update section, but I need a global or objectID:
return {
"result": $feature.assetid,
"edit": [{
"className": "electricdistributionassembly",
"updates": [{
"objectID": feature_objectid,
"associationType": 'container'
}]
}]
}
To make sure, this would work in AGOL field maps editor? Would I just pull the current objectID within the code?
To further clarify also, other calculated fields update automatically, like the "Freight Access Leg Direction Score" shown in the picture. But this field does not since its calculation involves other points.
My code is below in case it helps. It looks around for other features, but as I mentioned it requires me to update each point after one point is modified.
please forgive my lack of coding skill.
// get the current project and intersection name
var currentProj = $feature.Project;
var currentIntx = $feature.Intersection;
// Filter through the other points that have the same project and intersection name
var matchingProj = Filter($layer, "Project = '" + currentProj + "' AND Intersection = '" + currentIntx + "'");
// get list of all different cardinal directions within the filtered points
var allDirections = Distinct(matchingProj, "LegDirection");
// set initial total denmoniator of scoring ratio to 0
var totalSumDenominator = 0;
// set highest possible score values of different fields
var fieldsAndScores = {
Freight_VerticalClearance: 2,
Freight_CornerTurningRadii: 1,
Freight_TruckTurningMovement: 2,
};
// loop through each direction within the filter to get the total denominator
for (var f in allDirections) {
var currentDir = f.LegDirection;
var filteredFeatures = Filter(matchingProj, "LegDirection = '" + currentDir + "'");
for (var feat in filteredFeatures) {
var sumDenominator = 0;
for (var field in fieldsAndScores) {
if (!IsEmpty(feat[field])) {
sumDenominator += fieldsAndScores[field];
}
}
totalSumDenominator += sumDenominator;
}
}
// Add all values of the Freight Score for all features in the filter to get the numerator
var totalIntFreightScore = Sum(matchingProj, "Freight_AcessLegDirScore");
// if there is a score, divide the total score divided by total possible score
if (totalSumDenominator > 0) {
return Round(((totalIntFreightScore / totalSumDenominator) * 100), 2);
} else {
return 0; // Default value if the denominator is zero
}
Please post code as a code snippet:
for (var feat in matchingProj){
if (IsNull(feat.LegDirection)){
continue
}
var sumDenominator = 0;
for (var field in fieldsAndScores) {
if (!IsEmpty(feat[field])) {
sumDenominator += fieldsAndScores[field];
}
}
totalSumDenominator += sumDenominator;
}
What you want to do is get all the OIDs or GlobalID of the features you want to update. You are looping over them, so store them into a list/array.
When done, convert that list into a list of dictionaries, with the globalid and an attributes keyword, with the field you wish to update in it
Since this is an attribute rule, it always fires in the database, so it will work no matter what client does the edits. Some client are not aware of the return edit payload from apply edits(instead of the edit just returning success, it returns the others features that were edited so it can do a refresh). So if the client is not reading the return edits, you just need to refresh to see the other updates.
The return edit statement you want is the Updates:
return {
'edit': [{
'className': 'b_edit_dict',
'updates': [{
'globalID': '{7EBAB596-E9DB-40D8-9756-B2EBED2500B7}',
'attributes': {
'field_name': 22
}
}]
}]
}
Thank you, that is a big help. I think I'm getting much closer now. I don't get an error when in the code tester, but when editing a feature in the web map, it wont let me update the layer.
var currentProj = $feature.Project;
var currentIntx = $feature.Intersection;
var matchingProj = Filter($featureSet, "Project = @currentProj AND Intersection = @currentIntx");
var totalSumDenominator = 0;
var fieldsAndScores = {
Freight_VerticalClearance: 2,
Freight_CornerTurningRadii: 1,
Freight_TruckTurningMovement: 2,
Freight_OnStreetParking: 1,
Freight_DesignatedFreightRout: 2
};
var listOID = [];
var index = 0;
var attributesList = []; // Initialize an empty array for dictionaries
for (var feat in matchingProj){
listOID[index] = feat.OBJECTID;
index += 1; // Increment the index
if (IsNan(feat.LegDirection)){
continue
}
var sumDenominator = 0;
for (var field in fieldsAndScores) {
if (!IsEmpty(feat[field])) {
sumDenominator += fieldsAndScores[field];
}
}
totalSumDenominator += sumDenominator;
}
Console("List of OIDs: " + listOID);
// Add all values of the IntPedADAScore for all features in the filter
var totalIntFreightScore = Sum(matchingProj, "Freight_AcessLegDirScore");
// if (totalSumDenominator > 0) {
// var FinalScore = Round(((totalIntFreightScore / totalSumDenominator) * 100), 2);
// return FinalScore;
// } else {
// return 0; // Default value if the denominator is zero
// }
var FinalScore = Round(((totalIntFreightScore / totalSumDenominator) * 100), 2);
// Convert the listOID into a list of dictionaries
for (var oid in listOID) {
var attrDict = {
"OBJECTID": listOID[oid],
"Freight_AccessTotalScore": FinalScore
};
// Use the length of attributesList to append the new dictionary
attributesList[Count(attributesList)] = attrDict;
}
Console("List of Attributes: " + attributesList);
return {
'edit': [{
'className': FeatureSetById($map, "19130248331-layer-8"),
'updates': [{
attributesList
}]
}]
}
To be honest, I am not 100% sure. I am pretty new. This is a calculated expression being applied to a form within field maps. Perhaps I should have posted this in the AGOL forum? Or is what I am trying to do not possible.