Using ArcGIS Enterprise 10.9.1 - Field Maps version 21.4.0. I am curious if we are able to create an attribute rule to transfer a value from a related table to the parent feature class upon record submission?
I currently have attribute rules in place that transfers a water meter’s brand, meter ID, and latest reading from the parent feature class to the related work history table when the record is created. This is successful. I would like to then use another attribute rule on the feature class to automatically update the new meter ID once the new value is typed into the related work history table.
Is this type of workflow supported - actively transferring data from the parent feature to its related table and vice versa? If so, is the attribute rule created in the same manner? Unfortunately I’m not having successful results returning values from the related table back to the parent feature class.
Solved! Go to Solution.
Good morning. I went ahead and made sure the "Exclude from application evaluation" box was checked but I am still unfortunately seeing the same results. Attached are the error messages I have received within Pro. Again, thank you for your help.
I haven't had much success with placing the attribute rule on the related table to update the feature class. Just out of pure curiosity, I placed an attribute rule on the parent feature class with the following settings / expression.
Field: Meter_ID
Trigger: Insert / Update
var WM = FeatureSetByName($datastore, 'waterutilities.DBO.WorkHistoryTEST');
var water_meter = First(FeatureSetByRelationshipName($feature, "waterutilities.DBO.WaterMeterTOWorkHistory_TEST"))
var globalid = $feature.globalid
var filterStatement = 'Related_Asset = @globalid'
var related_data = Filter(WM, filterStatement)
var cnt = Count(related_data);
var results = "";
if ((cnt > 0) && (water_meter.Issue == 'MR')) {
for (var row in related_data) {
var line = row.New_MeterId;
results +=line;
}
} else {
results = "No related record";
}
return results;
The new Meter_ID is placed in the field on the FC (from the related table) after the record is created, but is appending the Meter_ID to whatever was previously there with each new record that is added. So, Meter ID of 7777 then becomes 77778888 when a new related record is added and then becomes 777788889999 when another record is added. Rather than just 8888 or 9999. Any ideas why?
It's because of this line: results +=line
What your code does is: go through ALL related work records and concatenate their New_MeterIDs. You need some way to check only the LATEST work record.
You shouldn't need the filter, as the FeatureSetByRelationshipName function returns only the related work records.
Note that, while this is absolutely a legit way of copying the new Meter_ID to the feature class, this won't happen automatically. You have to update the WaterMeter after you added a new WaterMeterWorkHistory record.
The first error comes from me not testing the rule. When no relates asset is found, the rule should just return, not return null.
Second error: no idea.
I built a rudimentary structure:
Feature class:
Table:
Relationship class:
Attribute rule on the work table:
// Calculation Attribute Rule on WaterMeterWorkHistory
// Triggers: Insert
// Exclude from application evaluation
// Copies old values from water meter t
// get the water meter
var water_meter = First(FeatureSetByRelationshipName($feature, "WaterMeterTOWorkHistory"))
if(water_meter == null) { return }
// get attributes from water_meter
var old_attributes = {
"Old_MeterID": water_meter.Meter_ID,
"Old_Brand": water_meter.Brand,
"Old_Reading": water_meter.Latest_Reading,
}
// map the attribute names from the work table to the feature class
var update_attribute_map = [
["New_MeterID", "Meter_ID"],
["New_Brand", "Brand"],
["New_Reading", "Latest_Reading"],
]
// 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[work_att]
var old_att = water_meter[asset_att]
if(!IsEmpty(new_att)) {
updated_attributes[asset_att] = new_att
}
}
var edit = [{"className": "WaterMeter", "updates": [{"globalID": water_meter.GlobalID, "attributes": updated_attributes}]}]
// return
return {
"result": {"attributes": old_attributes}, // copy old attributes from water meter to work table
"edit": edit // copy new attributes from work table to water meter
}
WaterMeter:
WaterMeterWorkHistory:
WaterMeter after these changes:
Hi, @JohannesLindner I really appreciate all the help you have given me thus far! I am admittedly new to arcade expressions / attribute rules so your assistance is really helpful. I hate to be nuisance, but for whatever reason it keeps telling me the fields in the first index [0] cannot be found for the $feature work history table. Everything appears to be set up correctly. From what I can tell, the fields are able to be found in the second index [1] water_meter FC.
Field "New_MeterId" cannot be found
Work History table fields
Water Meter FC fields
Hey! Busy week, sorry for ghosting you...
Sadly, I can't really help you here. The fields seem to be fine.
My only suggestion would be to rebuild the two tables in a test gdb and try it again, mabe there's some interference from other rules (or something else, idk).
Hi @JohannesLindner I just wanted to reach back out to you as a follow up and say that I finally have the expression working for me! Posted below is what ended up working for me where I had to specifically call out the field I wanted to use for the update. I then just applied the expression to individual fields when I set up the rule. I want to thank you for all your help and getting me on the correct path, it is really appreciated!
// Calculation Attribute Rule on WaterMeterWorkHistory table
// Triggers: Insert, Update
// Execution: Exclude from application evaluation
// Field: New_MeterId
var water_meter = First(FeatureSetByRelationshipName($feature, "WaterMeterTOWorkHistory"))
if($originalfeature.New_MeterId == $feature.New_MeterId) { return null }
// get attributes from water_meter
var old_attributes = {
"Meter_ID": water_meter.Meter_ID
}
// map the attribute names from the work table to the feature class
var update_attribute_map = [
["New_MeterId", "Meter_ID"]
]
// 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.New_MeterId
var old_att = water_meter[asset_att]
if(!IsEmpty(new_att)) {
updated_attributes[asset_att] = new_att
}
}
var edit = [{"className": "WaterMeter", "updates": [{"globalID": water_meter.GlobalID, "attributes": updated_attributes}]}]
return {
"edit": edit
}
This is awesome and it worked for me! However, I'm unable to get it to work with ArcGIS Online nor Field Maps. Any suggestions?
That's great, glad to hear you were able to use this as well! I have it currently working in Field Maps. What is the error you're receiving?
If it is working as it should in ArcGIS Pro, but in Field Maps you receive an "Arcade expression is invalid" error when you attempt to edit, it could be the version of Field Maps that is causing the issue. Ever since the 22.2.0 version was released, there have been issues when attribute rules are implemented. The temporary work around at least for that error was to make sure you checked "Exclude from Application Evaluation" for all the attribute rules in Pro and then re-publish the service.
That's really interesting. I'm actually not receiving any error message, it's simply that when I add a new related record on field maps, it's not autopopulating the respective attributes in the feature class like it does in ArcGIS Pro. I checked "Exclude from Application Evaluation" when I initially made the rule, so I don't believe that's the issue. And it's an online map, so I don't need to manually sync it. I have Field Maps version 22.3.0, and ArcGIS 2.9.3. In another thread, someone said that FeatureSetByRelationshipName has some bugs, but I don't know of any other ways to rewrite your code. Let me know if you have any other suggestions. I appreciate the help and I'm glad it's working for you!