Attribute Rule to pass a value from parent to child

5500
20
Jump to solution
12-08-2021 07:59 AM
dcamara924
New Contributor II

Hello. I'm attempting to pass a value from a parent feature to a related table using an Attribute Rule. The idea being that when a new related record is created it automatically populates this field based on its corresponding parent value. This seems like it should be easy to do but the arcade expression is proving challenging for my beginner level of arcade experience. The fields are both called "GPMDesign" and are both "Long" field types.  I'm running ArcGIS Pro 2.7.1 and Enterprise 10.8.1. Thank you!

0 Kudos
1 Solution

Accepted Solutions
JohannesLindner
MVP Frequent Contributor
// calculation attribute rule on child
// field: if you want to get only one field from the parent, then chose 
// that field. if you want to get multiple fields, leave empty
// triggers: Insert(, update)

// load the related parent features using one of these methods
// if you have a relationship class between parent and child:
var parent_fs = FeatureSetByRelationshipName($feature, "RelationshipName")
// if not
var parent_fs = FeatureSetByName($datastore, "NameOfParentFC")
var key = $feature.ForeignKeyField
parent_fs = Filter(parent_fs, "PrimaryKeyField = @key")

// return nothing if no parent feature was found
var parent = First(parent_fs)
if(parent == null) { return }

// if you want to return only one field:
return parent.Field

// if you want to return multiple fields:
var att = {
  "Field1": parent.Field1,
  "Field2": parent.Field2
}
return {"result": {"attributes": att}}

 


Have a great day!
Johannes

View solution in original post

20 Replies
JoeBorgione
MVP Emeritus

Take a look at the ESRI Address Data Management Solution; it has similar rules written between address points and related site address points. There is an aprx you can download that has sample data and the rules are applied there.

That should just about do it....
dcamara924
New Contributor II

Thanks Joe. I think I found what you were referring to in one of the web map's pop up configurations. Neither the tables or feature layers had actual Attribute Rules on them that I could see. It still seems way more complicated than it should though. I'll keep tinkering with the FeatureSet functions.

0 Kudos
JoeBorgione
MVP Emeritus

The rules are fairly complicated, but I can find them by Right Clicking on Address Points in the table of contents, selecting Design and then Attribute Rules.  In the solution, the work flow has the user drop an Address Point on a street centerline and through a relationship class a Site Address Point is created.

 

JoeBorgione_0-1638990286653.png

 

That should just about do it....
0 Kudos
JohannesLindner
MVP Frequent Contributor
// calculation attribute rule on child
// field: if you want to get only one field from the parent, then chose 
// that field. if you want to get multiple fields, leave empty
// triggers: Insert(, update)

// load the related parent features using one of these methods
// if you have a relationship class between parent and child:
var parent_fs = FeatureSetByRelationshipName($feature, "RelationshipName")
// if not
var parent_fs = FeatureSetByName($datastore, "NameOfParentFC")
var key = $feature.ForeignKeyField
parent_fs = Filter(parent_fs, "PrimaryKeyField = @key")

// return nothing if no parent feature was found
var parent = First(parent_fs)
if(parent == null) { return }

// if you want to return only one field:
return parent.Field

// if you want to return multiple fields:
var att = {
  "Field1": parent.Field1,
  "Field2": parent.Field2
}
return {"result": {"attributes": att}}

 


Have a great day!
Johannes
dcamara924
New Contributor II

Thanks Johannes! This helped me develop what I was looking for. Simple and straightforward. Much appreciated.

0 Kudos
HMarcks
New Contributor III

Fingers crossed that someone may still be following this thread.

I am trying to alter this code to 1) go from children to parent and 2) with a sum on the child field instead of the first record being transferred.  I have so far only managed to successfully complete 1.  I have tried various ways of using Sum() in different locations and finally came to a way where it didn't give me an error but it still only give me the first record not the sum.

 

I am totally new to python so I am just using trial and error here and apologize if the answer is looking right back at me but any help would be appreciated.

/// calculation attribute rule on parent
// field: if you want to get only one field from the child, then chose 
// that field. if you want to get multiple fields, leave empty
// triggers: Insert(, update)

// load the related child features using one of these methods
// if you have a relationship class between parent and child:
var child_fs = FeatureSetByRelationshipName($feature, "ApplicationSite_TurfArea", ['Area'])

// return nothing if no child feature was found
var child =  sum($feature,child_fs)
if(child == null) { return }

// if you want to return only one field:
return child


return {"result": {"attributes": att}}

 

Additionally this is going to get more complicated as I want to eventually create a sum from the Area based on the input for another field.  i.e. some all child areas that have "post inspection" in the Status field. But I found that if I work out one piece of a code at a time I can try to piece them together.

0 Kudos
JohannesLindner
MVP Frequent Contributor

Sum() takes a Featureset and a field als arguments.

I included a Filter() to search for the value in the status field.

var child_fs = FeatureSetByRelationshipName($feature, "ApplicationSite_TurfArea", ['Area', 'Status'])
var filterd_child_fs = Filter(child_fs, "Status = 'post inspection'")
return Sum(filterd_child_fs, "Area")

 


Have a great day!
Johannes
HMarcks
New Contributor III

Amazing! Thank you.

I was starting to come to this conclusion yesterday but I could not quite figure out how to "word" the filter and just kept getting errors.  Works great now and I have duplicated it to provide the totals for all of our different statuses into the parent field.

 

var child_fs = FeatureSetByRelationshipName($feature, "ApplicationSite_TurfArea", ['Area', 'Status'])

var filterd_child_fs = Filter(child_fs, "Status = 2")
if(filterd_child_fs == null) { return }

return Sum(filterd_child_fs, "Area")

 

 

With the help of this blog https://github.com/Esri/arcade-expressions/blob/master/attribute_rule_calculation/UpdateParentFeatur... I was also able to add an event to the child fields to trigger the recalculation if only they were edited and not the parent field.

 

// This rule will update an attribute in the parent feature

// Store the parent feature global from the key field in the relationship
var parent_id = $feature.GUIDApplicationSite;
if (IsEmpty(parent_id))
    return parent_id;

// force to upper as the sql is case sensitive
parent_id = Upper(parent_id);

// Using the GDB name, get the parent classes records and Global ID field
var parent_class = FeatureSetByName($datastore, "ApplicationSite", ["globalid", 'laststatus'], false);
// Filter the parent class for only related features
var parent_records = Filter(parent_class, "globalid = @parent_id");

var updates = [];
var i = 0;
var new_value = 0;

if (IsEmpty($feature.Status) == False)
{
    new_value = $feature.Status
}

// Loop through each  feature, create a dict of the Global ID and the new value date
for (var row in parent_records) {
    // If the parent row is null or has a different value, updated it
    if (IsEmpty(row['laststatus']) || row['laststatus'] != new_value)
    {
        updates[i++] = {
            'globalid': parent_id,
            'attributes': {"laststatus": new_value}    
        };
    }
}

// Return the original value in the result parameter, as to not lost the entered value
// Using the edit parameter,  return the class and list of updates
return {
'result': parent_id,
'edit': [
            {'className': 'ApplicationSite',
             'updates': updates
            } 
        ]
};

 

 I probably could have simplified it better since I am not looking through multiple fields to get the status but it all seems to work very nicely now.

I am a little curious what will happen to all this when I transfer it to AGOL so it can be used in field maps LOL but I guess I will find out soon enough.

Thank you, again.

0 Kudos
PetronellaHauptmann1
New Contributor II

Hi!

I'm trying this and can't make it work somehow.

My feature class, relationship class and table are stored in an sde database. I have a relationship class between parent and child. My script looks like this. It validates but when I create a new feature the field in which the attriute rule is applied won't update.

// calculation attribute rule on child
// field: if you want to get only one field from the parent, then chose
// that field. if you want to get multiple fields, leave empty
// triggers: Insert(, update)

// load the related parent features using one of these methods
// if you have a relationship class between parent and child:
var parent_fs = FeatureSetByRelationshipName($feature, "Matstallen_Rate", ['Namn'])

// return nothing if no parent feature was found
var parent = First(parent_fs)
if (parent == null) { return }

// if you want to return only one field:
return parent

Super thankful for your help

0 Kudos