Select to view content in your preferred language

Attribute rule to actively transfer data from a related table to it’s parent feature class and vice versa

6225
36
Jump to solution
02-07-2022 04:35 PM
tbearb
by
New Contributor III

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.

0 Kudos
36 Replies
tbearb
by
New Contributor III

Is this issue only occurring with ArcGIS Online? Are you guys using Portal as well? I have only tried this with data that is registered with an SDE / utilized in an enterprise deployment. But essentially all I did was publish my layers from ArcGIS Pro and then created a web map with those layers in it to be used in Field Maps.

Also, if you don't mind, post your code and I can see if I can point out anything.

0 Kudos
dommybo123
New Contributor II

Hmm, I wonder if my issue is related to using a FileGDB instead of an SDE. We have data stored on the SDE, but since I'm experimenting with this I was just using local copies of the data.

I tried using it on the data from the SDE, but now I'm getting an error that I hadn't gotten before: Screenshot (14).png

Not quite sure what that is about. The parent class has the appropriate field.

Here's my code:

PlantCenter is the parent class. Pruning_Maintenance is the child related table. And they are related by the PlantCenter2Pruning_Maintenance relationship class

// Calculation Attribute Rule on Pruning_Maintenance table
// Triggers: Insert, Update
// Execution: Exclude from application evaluation
// Field: LastPruningDate

var prune_date = First(FeatureSetByRelationshipName($feature, "PlantCenter2Pruning_Maintenance", ['*'], false))
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": "PlantCenter", "updates": [{"globalID": prune_date.GlobalID_1, "attributes": updated_attributes}]}]

return {
  "edit": edit
}

Thanks so much for all your help!

0 Kudos
tbearb
by
New Contributor III

That is interesting for sure. I wonder since you're using the data from the SDE it is now wanting you to provide the fully qualified name for the relationship class as well as the parent feature class. So for example, "PlantCenter2Pruning_Maintenance" now becomes "xxxxxxx.DBO.PlantCenter2Pruning_Maintenance". Same with "PlantCenter" becoming "xxxxx.DBO.PlantCenter".

I also noticed you guys have GlobalID_1 rather than just GlobalID. I'm not sure if that would cause any quirks. 

0 Kudos
dommybo123
New Contributor II

You were right on both ends. Changing the naming made the attribute rule work as intended. Thanks for pointing that out! For some reason, even though this data is stored in the SDE, the attribute rules are still not working when I publish the Web Map and make updates using Field Maps. From conversations with Esri staff, it sounds like there just isn't widespread support for attribute rules on AGOL or Field Maps yet. I might try to run a Python script that can effectively achieve the same goal, but just runs once nightly. Thanks for all your help, and if you can think of anything else to try let me know! 

0 Kudos
tbearb
by
New Contributor III

I know I did come across an issue at one point but I am honestly having a hard time remembering what that was exactly. Can you swap out the following two lines of code at the beginning to see if you experience different results? Be sure to republish after the rule is updated in ArcGIS Pro. I know this was one of the changes I ended up making:

Original lines:

var prune_date = First(FeatureSetByRelationshipName($feature, "PlantCenter2Pruning_Maintenance", ['*'], false))
if($originalfeature.LastPruningDate == $feature.LastPruningDate) { return null }

New lines:

var prune_date = First(FeatureSetByRelationshipName($feature, "xxxxxxxxx.DBO.PlantCenter2Pruning_Maintenance"))
if(prune_date == null) { return "missing value" }

Also, just for confirmation, in looking at your code I see that you have a field in both the related table as well as the feature class each called, "LastPruningDate". I just wanted to make sure that was indeed the case?

0 Kudos
Sothea_VOEUN
New Contributor III

It's the same problem as mine. I got an error while executing the code in ArcGIS Online 3.0.0

 

0 Kudos
Gene_Sipes
Occasional Contributor

I am hoping this can help me! I am trying to do something similar. I want to have an inserted value on a related table update a field on the parent FC. Currently testing in a FGDB, but with hopes to port over to the enterprise DB. I am trying to emulate your script above using my setup but I am not sure where to replace my FC, related table, and field names in your script. Can you provide me some context on what each of the variables and references to water_meter etc, mean? I would greatly appreciate it. 

0 Kudos
tbearb
by
New Contributor III

Hi @Gene_Sipes, hopefully this will clarify some things for you. This script is specifically used to update a water meter's brand (FC) based on whatever value is typed in the related work history table. The attribute is applied to a specific field on the related work history table.

//Update the Meter's brand from the Work History table
//Field: NewMeterBrand
//Triggers: Insert, Update
//Execution: Exclude from application evaluation
var water_meter = First(FeatureSetByRelationshipName($feature, "xxxxxxxx.DBO.WaterMeterTOWorkHistory"))
if(water_meter == null) { return "missing value" }

// get attributes from water_meter
var old_attributes = {
  "Meter_Brand": water_meter.Meter_Brand
}

// map the attribute names from the work table to the feature class
var update_attribute_map = [
  ["NewMeterBrand", "Meter_Brand"]
]

// 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.NewMeterBrand
  var old_att = water_meter[asset_att]
  if(!IsEmpty(new_att)) {
    updated_attributes[asset_att] = new_att
  }
}
var edit = [{"className": "xxxxxxx.DBO.WaterMeter", "updates": [{"globalID": water_meter.GlobalID, "attributes": updated_attributes}]}]

return {
  "edit": edit
}

In this scenario:

Relationship name = xxxxxxxx.DBO.WaterMeterTOWorkHistory

Parent feature class = xxxxxxx.DBO.WaterMeter

Field on related work history table = NewMeterBrand

Field on parent feature class = Meter_Brand

If I remember correctly, "water_meter" is just a variable that is used throughout the script that references the parent feature class.

 

0 Kudos
ChristopherBowering
Occasional Contributor III

Hi there.  I am interested in doing what you have already accomplished successfully - using an attribute rule to transfer parent feature class attributes to a related table.  Would you be able to share your workflow/arcade script for that?  My nuances would be combining (summation) a few fields' worth of attributes from the parent with a few from the child (these child fields populated once child record is created) to come up with a single number.  However, one step at a time!  Thank you.

0 Kudos
tbearb
by
New Contributor III

Hi, @ChristopherBowering, glad you found this useful. Here is the attribute rule we have running in the background on the related table that passes an attribute from the parent feature class (xxxxxxxxxxx.DBO.WaterMeter) to the related table.

Here, the last recorded meter reading (field = Current_Read) will get transferred to the related work history table's field called "Old_Read". You'll see I have lots of else if lines here, but that is only because I wanted the rule to be triggered when certain Issue subtypes were selected for the related table when a record was being created.

 

//Pass old read to Work History
//Field: Old_Read
//Triggers: Insert, Update
//Execution: N/A
var WM = FeatureSetByName($datastore, 'xxxxxxxxxx.DBO.WaterMeter');
var globalid = $feature.Related_Asset
var filterStatement = 'globalid = @globalid'
var related_data = Filter(WM, filterStatement)
var cnt = Count(related_data);

var results = "";

if ((cnt > 0) && ($feature.Issue == 'MR')) {
 for (var row in related_data) {
  var line = row.Current_Read;
  results +=line;
 }
} else if ((cnt > 0) && ($feature.Issue == 'L')) {
 for (var row in related_data) {
  var line = row.Current_Read;
  results +=line;
 }
} else if ((cnt > 0) && ($feature.Issue == 'TR')) {
 for (var row in related_data) {
  var line = row.Current_Read;
  results +=line;
 }
} else if ((cnt > 0) && ($feature.Issue == 'BL')) {
 for (var row in related_data) {
  var line = row.Current_Read;
  results +=line;
 }
} else if ((cnt > 0) && ($feature.Issue == 'F')) {
 for (var row in related_data) {
  var line = row.Current_Read;
  results +=line;
 }
} else if ((cnt > 0) && ($feature.Issue == 'MB')) {
 for (var row in related_data) {
  var line = row.Current_Read;
  results +=line;
 }
} else {
 results = "No related record";
}
return results;

 

 

0 Kudos