I am trying to create an attribute rule that updates the GIS_PropertyAcres field across all features that all share a common Parent Property ID when the geometry of a feature is updated. I am constantly getting a Does anyone know how to modify the following code to prevent this error from occurring?
//Creates empty array and counter for iterating
var updates = []
var counter = 0
var id = $feature.ParentPropertyID
var fs = Filter($featureset, "ParentPropertyID = @ID")
var newacres = Sum(fs, "GIS_TractAcres")
var new_shape_area = $feature.Shape_Area
var old_shape_area = $originalfeature.Shape_Area
var cnt_poly = count(fs)
if (new_shape_area != old_shape_area){
for (var f in fs){
updates[counter] = {
'globalid': f.GlobalId,
'attributes':{
'GIS_PropertyAcres': newacres,
}
}
counter++
}
return {
'edit': [{
'className': 'Arcade_Rules_Test',
'updates': updates
}]
}
}
else {
return $originalfeature.GIS_PropertyAcres
}
Solved! Go to Solution.
When you return a dictionary with update instructions, these updates trigger the rule again. You have it set up so that the same feature gets updated over and over and over, so at some point ArcGIS halts the loop and errors out.
I think you have the right idea in line 11: You need to check whether the attribute you care about was changed by the update. If not, you don't need to return further update instructions. I'm not really sure why your condition isn't working, and I honestly don't feel like diving too deep into it...
Anyway, here is an expression that should work as expected. It updates both GIS_TractAcres and GIS_PropertyAcres, so you only need this one rule. It also handles deleting features properly.
// Calculation Attribute Rule
// field: empty
// triggers: Insert, Update, Delete
// exclude from application evaluation
var mode = $editcontext.editType
// abort if this is an update that doesn't change the geometry
if(mode == "UPDATE" && Equals(Geometry($feature), Geometry($originalfeature))) {
return
}
// get all OTHER features with this ID
var id = $feature.ParentPropertyID
var gid = $feature.GlobalID
var query = "ParentPropertyID = @ID AND GlobalID <> @gid"
var fs = Filter($featureset, query)
// get this area and the sum of the other areas
var f_area = Area($feature, "acres")
var total_area = Sum(fs, "GIS_TractAcres")
// if this is an insert or update, add this area to the total (don't do it if this is a delete)
if(mode != "DELETE") {
total_area += f_area
}
// construct the update array
var updates = []
for(var f in fs) {
if(f.GlobalID == $feature.GlobalID) { continue }
var u = {
globalID: f.GlobalID,
attributes: {
GIS_PropertyAcres: total_area
}
}
Push(updates, u)
}
return {
result: {
attributes: {
GIS_TractAcres: f_area,
GIS_PropertyAcres: total_area}
},
edit: [{
className: "Arcade_Rules_Test",
updates: updates
}]
}
When you return a dictionary with update instructions, these updates trigger the rule again. You have it set up so that the same feature gets updated over and over and over, so at some point ArcGIS halts the loop and errors out.
I think you have the right idea in line 11: You need to check whether the attribute you care about was changed by the update. If not, you don't need to return further update instructions. I'm not really sure why your condition isn't working, and I honestly don't feel like diving too deep into it...
Anyway, here is an expression that should work as expected. It updates both GIS_TractAcres and GIS_PropertyAcres, so you only need this one rule. It also handles deleting features properly.
// Calculation Attribute Rule
// field: empty
// triggers: Insert, Update, Delete
// exclude from application evaluation
var mode = $editcontext.editType
// abort if this is an update that doesn't change the geometry
if(mode == "UPDATE" && Equals(Geometry($feature), Geometry($originalfeature))) {
return
}
// get all OTHER features with this ID
var id = $feature.ParentPropertyID
var gid = $feature.GlobalID
var query = "ParentPropertyID = @ID AND GlobalID <> @gid"
var fs = Filter($featureset, query)
// get this area and the sum of the other areas
var f_area = Area($feature, "acres")
var total_area = Sum(fs, "GIS_TractAcres")
// if this is an insert or update, add this area to the total (don't do it if this is a delete)
if(mode != "DELETE") {
total_area += f_area
}
// construct the update array
var updates = []
for(var f in fs) {
if(f.GlobalID == $feature.GlobalID) { continue }
var u = {
globalID: f.GlobalID,
attributes: {
GIS_PropertyAcres: total_area
}
}
Push(updates, u)
}
return {
result: {
attributes: {
GIS_TractAcres: f_area,
GIS_PropertyAcres: total_area}
},
edit: [{
className: "Arcade_Rules_Test",
updates: updates
}]
}