Hi there,
I successfully set up an attribute rule in ArcGIS Pro that automatically updates attributes in a parent feature class once the child related table is modified. The idea behind this is when people update the most recent date of maintenance (in field maps), the parent feature class automatically stores the most recent date of maintenance as well.
The issue is, once I published this data as a web map and updated the related table in Field Maps, the changes do not transfer over to the parent feature class like they did in ArcGIS Pro. Does anyone know why this is? I tried to play around with calculated fields in Field Maps but when I copied the arcade expression from ArcGIS Pro into Field Maps, Field Maps gave me an error saying "Field Could Not Be Calculated."
I'm unsure what to do since the whole purpose of this attribute rule is to function with Field Maps. Any help is greatly appreciated! Here is my attribute rule code for reference (ignore the sloppy naming conventions):
// Calculation Attribute Rule on PruneMaint table
// Triggers: Insert, Update
// Execution: Exclude from application evaluation
// Field: LastPruningDate
var prune_date = First(FeatureSetByRelationshipName($feature, "PruneMaintenance2PruneMaint"))
if($originalfeature.LastPruningDate == $feature.LastPruningDate) { return null }
// get attributes from prune_date
var old_attributes = {
"LastPruneDate": prune_date.LastPruningDate
}
// map the attribute names from the work table to the feature class
var update_attribute_map = [
["LastPruningDate", "LastPruningDate"]
]
// if the new attributes are filled in, add them to the edit request
var updated_attributes = Dictionary()
for(var i in update_attribute_map) {
var work_att = update_attribute_map[i][0]
var asset_att = update_attribute_map[i][1]
var new_att = $feature.LastPruningDate
var old_att = prune_date[asset_att]
if(!IsEmpty(new_att)) {
updated_attributes[asset_att] = new_att
}
}
var edit = [{"className": "PruneMaintenance40", "updates": [{"globalID": prune_date.GlobalID, "attributes": updated_attributes}]}]
return {
"edit": edit
}
It has been posted a few times that FeatureSetByRelationshipName has bugs in it. I know one was having a . in the name.
Instead use By name and then a filter like this. It may be slower on big tables but it works.
var sql = "PointID = '" + $feature.PointID + "'";
var tbl = Filter(FeatureSetByName($map,"Points", ['CollectCoreSubset1'], false), sql);
hope that helps
I've also seen people having a lot of issues with FeatureSetByRelationshipName
For some reason, when I do FeatureSetByName, I get an error message: "A requested row object could not be located [ "
When I tested out the prune_date variable, using FeatureSetByRelationshipName returns type Null. When using FeatureSetByName, it returns type Feature. Because of this, I think it doesn't function with the rest of my code's logic (which I copied from another Esri community post). Are there any other workarounds you'd recommend? I'm brand new to Arcade (and have no Javascript background), so I can't really generate much on my own yet.
Here's my current code, I believe the issue is on line 19 with the array:
// Calculation Attribute Rule on PruneMaint table
// Triggers: Insert, Update
// Execution: Exclude from application evaluation
// Field: LastPruningDate
var sql = "GlobalID = '" + $feature.GlobalID + "'";
var sql = Upper(sql)
var prune_date = First(Filter(FeatureSetByName($datastore,"PruneMaint", ['*'], false), sql));
// old var prune_date = First(FeatureSetByRelationshipName($feature, "PruneMaintenance2PruneMaint"))
if($originalfeature.LastPruningDate == $feature.LastPruningDate) { return null }
// get attributes from prune_date
var old_attributes = {
"LastPruneDate": prune_date.LastPruningDate
}
// map the attribute names from the work table to the feature class
var update_attribute_map = [
["LastPruningDate", "LastPruningDate"]
]
// if the new attributes are filled in, add them to the edit request
var updated_attributes = Dictionary()
for(var i in update_attribute_map) {
var work_att = update_attribute_map[i][0]
var asset_att = update_attribute_map[i][1]
var new_att = $feature.LastPruningDate
var old_att = prune_date[asset_att]
if(!IsEmpty(new_att)) {
updated_attributes[asset_att] = new_att
}
}
var edit = [{"className": "PruneMaintenance40", "updates": [{"globalID": prune_date.GlobalID, "attributes": updated_attributes}]}]
return {
"edit": edit
}
Sorry I knew I should have posted the full code but thought it was not relevant.
You have First but you need to tell it which field you want like this.
var sql = "PointID = '" + $feature.PointID + "'";
var tbl = Filter(FeatureSetByName($map,"Points", ['DesignLong'], false), sql);
return First(tbl).DesignLong
That makes sense. Unfortunately, I'm getting the same error message. Perhaps something else went awry with my code?
// Calculation Attribute Rule on PruneMaint table
// Triggers: Insert, Update
// Execution: Exclude from application evaluation
// Field: LastPruningDate
// old way -> var water_meter = First(FeatureSetByRelationshipName($feature, "PruneMaintenance2PruneMaint"))
var sql = "GlobalID = '" + $feature.GlobalID + "'";
var sql = Upper(sql);
var prune_date_filter = Filter(FeatureSetByName($datastore,"PruneMaint", ['GlobalID','LastPruningDate'], false), sql);
var prune_date = First(prune_date_filter);
if($originalfeature.LastPruningDate == $feature.LastPruningDate) { return null }
// get attributes from water_meter
var old_attributes = {
"LastPruneDate": prune_date.LastPruningDate
}
// map the attribute names from the work table to the feature class
var update_attribute_map = [
["LastPruningDate", "LastPruningDate"]
]
// if the new attributes are filled in, add them to the edit request
var updated_attributes = Dictionary()
for(var i in update_attribute_map) {
var work_att = update_attribute_map[i][0]
var asset_att = update_attribute_map[i][1]
var new_att = $feature.LastPruningDate
var old_att = prune_date[asset_att]
if(!IsEmpty(new_att)) {
updated_attributes[asset_att] = new_att
}
}
var edit = [{"className": "PruneMaintenance40", "updates": [{"globalID": prune_date.GlobalID, "attributes": updated_attributes}]}]
return {
"edit": edit
}
Few things. You are converting your sql to Uppercase. That would change GlobalID to GLOBALID which may be causing the issue. If you are worried about the id it self then just upper that like
var sql = "GlobalID = '" + Upper($feature.GlobalID) + "'";
You have $datastore in your FeatureSet call. Should be $map like my example IF you are in a webmap. In ArcMap and I am really not sure but it may work. If you use datastore you have to give it something different than just the layer name but I am not seeing a doc on how. datastore may be going to your scratch who knows.
In Ops Dashboard I had to use the PortalID call instead. Then it should always be able to find it.
It looks like this if using AGOL. The ItemID and layer number come from the AGOL item page of the service.
var p = 'https://arcgis.com/';
var tbl = FeatureSetByPortalItem(Portal(p),'d12b26608e184286a35f6da09',9,['UnknownCode'], geometry = false);
Hope that does it. I would troubleshoot but seeing what the Count() of prune_date_filter is. That way you can see if it is getting anything back at all first. Easier for testing. Can use Console to output to the screen.