Related Record Attributes in Pop-up Display with Arcade Expression

1625
9
Jump to solution
08-02-2021 08:46 AM
RyanElvrum2
New Contributor II

My goal is to create a pop-up expression using Arcade to show attribute values from a filtered related table two-relationships deep.

My data is related as follows;

Service Location (Point feature) --> Service Account (Table) --> Meters (Table)

I am able to create an pop-up expression for the Service Location that returns attributes from the related Service Account table, but I would like to go one level deeper and also return attributes from the related Meter table.

Currently my Arcade expression is;

var ServiceLocationGID = $feature.GlobalID
var ServiceAccounts = FeatureSetByName($map,"Service Account - Electric")
var filterstatement = 'ServiceLocationGID = @ServiceLocationGID'

var relatedData = Filter(ServiceAccounts, filterstatement)

var popupString = ''
for ( var f in relatedData){

popupString += "First Name: " + Text(Proper(f.firstname)) + TextFormatting.Newline
+ "Last Name: " + Proper(f.lastname) + TextFormatting.Newline
+ "Service Address 1: " + Proper(f.serviceaddr1) + TextFormatting.Newline
+ "Service Address 2: " + Proper(f.serviceaddr2) + TextFormatting.Newline
+ "Account Number: " + f.AccountNumber + TextFormatting.Newline + TextFormatting.Newline
}
return popupString

 

I am unsure on how to format the expression to then filter the meter table and return attribute values from the related record to include in my pop-up string.

0 Kudos
1 Solution

Accepted Solutions
XanderBakker
Esri Esteemed Contributor

Hi @RyanElvrum2 ,

 

Do you have multiple meters for a single service account? If so, you will only get a single meter in the pop-up string. Also, the meter number does not need to be cast to string since this will always be a string when cascading a text with other information. 

Try this: 

var ServiceLocationGID = $feature.GlobalID;
var SqlServiceAccounts = "ServiceLocationGID = @ServiceLocationGID";

var ServiceAccounts = FeatureSetByName($map, "ServiceAccounts");
var RelatedServiceAccounts = Filter(ServiceAccounts, SqlServiceAccounts);

var Meters = FeatureSetByName($map, "Meters");
var popupstring = "";
for (var ServiceAccount in RelatedServiceAccounts){
    
    popupstring += "First Name:  " + Text(Proper(ServiceAccount.firstname)) + TextFormatting.Newline;
    popupstring += "Last Name:  " + Proper(ServiceAccount.lastname) + TextFormatting.Newline;
    popupstring += "Service Address 1:  " + Proper(ServiceAccount.serviceaddr1) + TextFormatting.Newline;
    popupstring += "Service Address 2:  " + Proper(ServiceAccount.serviceaddr2) + TextFormatting.Newline;
    popupstring += "Account Number: " + ServiceAccount.AccountNumber + TextFormatting.Newline;
    
    var ServiceAccountGID = ServiceAccount.GlobalID;
    var SqlMeters = "ServiceAccountGID = @ServiceAccountGID";
    
    var RelatedMeters = Filter(Meters, SqlMeters);
    for (var Meter in RelatedMeters) {
        popupstring += " - Meter Number: " + Meter.MeterID + TextFormatting.Newline;
    }
    popupstring += TextFormatting.Newline;
}

Return popupstring;

View solution in original post

9 Replies
RyanElvrum2
New Contributor II
0 Kudos
XanderBakker
Esri Esteemed Contributor

Hi @RyanElvrum2 ,

 

I would probably use a nested FeatureSetByRelationshipName function like this if you have a nested relationship:

// Service Location (Point feature) --> Service Account (Table) --> Meters (Table)

// get the feature, which is the service location
var servicelocation = $feature;

// use the service location and the relationship to drill down to service accounts
var serviceaccounts = FeatureSetByRelationshipName(servicelocation, "Relationship name for Service Location to Service Account", ['*'], false);

// loop through the service accounts
for (var serviceaccount in serviceaccounts) {
    // include info of the service account?
    // use the service account to drill down to the meter information
    var meters = FeatureSetByRelationshipName(serviceaccount, "Relationship name for Service Account to Meters", ['*'], false);

    // loop through the meters
    for (var meter in meters) {
        // do something with the meter information
    }    
}

  

0 Kudos
RyanElvrum2
New Contributor II

Thanks for the response Xander. After looking into this a bit, I am assuming the "FeatureSetByRelationshipName" function is not available to me. I am trying to configure this arcade expression in Portal on an ArcGIS Enterprise Server 10.7.1.

 

Any ideas for a workaround assuming the above function is not available to me?

0 Kudos
XanderBakker
Esri Esteemed Contributor

Hi @RyanElvrum2 ,

 

I am afraid that is true. This function was introduced at version 1.8 of Arcade and Enterprise 10.7.1 has version 1.7 of Arcade.

Your initial code that uses a Filter function and a SQL query would be the right way to go. And when nesting this twice you should be able to get to the meter information. 

An example of this is shown below: 

// Service Location (Point feature) --> Service Account (Table) --> Meters (Table)

// get the value of the service location feature that connects to the service accounts
var ServiceLocationValueToQueryFor = $feature["FieldNameServiceLocationValue"];

// create SQL expression
var SqlServiceAccounts = "SomeField = @ServiceLocationValueToQueryFor";

// filter the related service accounts
var ServiceAccounts = FeatureSetByName($map, "Name of the ServiceAccounts table in the map");
var RelatedServiceAccounts = Filter(ServiceAccounts, SqlServiceAccounts);

// loop through the service accounts
var Meters = FeatureSetByName($map, "Name of the Meters table in the map");
for (var ServiceAccount in RelatedServiceAccounts) {
    // include info of the service account?
    var MeterValueToQueryFor = ServiceAccount["FieldNameMaterValue"];
    var SqlMeters = "SomeField = @MeterValueToQueryFor";
    // use the service account to drill down to the meter information
    var RelatedMeters = Filter(Meters, SqlMeters);

    // loop through the meters
    for (var Meter in RelatedMeters) {
        // do something with the meter information
    }    
}
RyanElvrum2
New Contributor II

Xander, again thank you for your reply. I've been working away at this for a few hours now. I am having issues as soon as I get to line 15. I get an error message about an undefined variable (I am assuming the variable is 'ServiceAccount')

I wonder if this issue is related to the relationship types between the features. All relationships are a 1:M, so 1 Service Location can have multiple Service Accounts related to it, and 1 Service Account can have multiple Meters related to it.

 

Any insight here?

0 Kudos
RyanElvrum2
New Contributor II

@XanderBakker 

***Edit***

This expression was close, but Xander pointed out that it will only return 1 meter number value, when instead I needed all meter numbers related to the account. Xander has the solution below

 

 

var ServiceLocationGID = $feature.GlobalID
var SqlServiceAccounts = "ServiceLocationGID = @ServiceLocationGID"

var serviceaccounts = FeatureSetByName($map,"ServiceAccounts")
var RelatedServiceAccounts = Filter(ServiceAccounts, SqlServiceAccounts)

var meters = FeatureSetByName($map,"Meters")
var popupstring = ''
for (var serviceaccount in RelatedServiceAccounts){
    
    var FirstName = "First Name:  " + Text(Proper(serviceaccount.firstname)) + TextFormatting.Newline
    var LastName = "Last Name:  " + Proper(serviceaccount.lastname) + TextFormatting.Newline
    var ServiceAddress1 = "Service Address 1:  " + Proper(serviceaccount.serviceaddr1) + TextFormatting.Newline
    var ServiceAddress2 = "Service Address 2:  " + Proper(serviceaccount.serviceaddr2) + TextFormatting.Newline
    var AccountNumber = "Account Number: " + serviceaccount.AccountNumber + TextFormatting.Newline
    
    var ServiceAccountGID = serviceaccount.GlobalID
    var SqlMeters = "ServiceAccountGID = @ServiceAccountGID"
    
    var RelatedMeters = Filter(Meters, SqlMeters)
    for (var meter in RelatedMeters){
        Var MeterNumber = "Meter Number: " + meter.MeterID + TextFormatting.Newline
    }
    popupstring += Firstname 
    + LastName 
    + ServiceAddress1 
    + ServiceAddress2 
    + AccountNumber 
    + text(MeterNumber) 
    + TextFormatting.Newline
}
Return popupstring

 

 

0 Kudos
XanderBakker
Esri Esteemed Contributor

Hi @RyanElvrum2 ,

 

Do you have multiple meters for a single service account? If so, you will only get a single meter in the pop-up string. Also, the meter number does not need to be cast to string since this will always be a string when cascading a text with other information. 

Try this: 

var ServiceLocationGID = $feature.GlobalID;
var SqlServiceAccounts = "ServiceLocationGID = @ServiceLocationGID";

var ServiceAccounts = FeatureSetByName($map, "ServiceAccounts");
var RelatedServiceAccounts = Filter(ServiceAccounts, SqlServiceAccounts);

var Meters = FeatureSetByName($map, "Meters");
var popupstring = "";
for (var ServiceAccount in RelatedServiceAccounts){
    
    popupstring += "First Name:  " + Text(Proper(ServiceAccount.firstname)) + TextFormatting.Newline;
    popupstring += "Last Name:  " + Proper(ServiceAccount.lastname) + TextFormatting.Newline;
    popupstring += "Service Address 1:  " + Proper(ServiceAccount.serviceaddr1) + TextFormatting.Newline;
    popupstring += "Service Address 2:  " + Proper(ServiceAccount.serviceaddr2) + TextFormatting.Newline;
    popupstring += "Account Number: " + ServiceAccount.AccountNumber + TextFormatting.Newline;
    
    var ServiceAccountGID = ServiceAccount.GlobalID;
    var SqlMeters = "ServiceAccountGID = @ServiceAccountGID";
    
    var RelatedMeters = Filter(Meters, SqlMeters);
    for (var Meter in RelatedMeters) {
        popupstring += " - Meter Number: " + Meter.MeterID + TextFormatting.Newline;
    }
    popupstring += TextFormatting.Newline;
}

Return popupstring;

View solution in original post

RyanElvrum2
New Contributor II

@XanderBakker  You're the best! Your expression gave me exactly what I was looking for, and I appreciate the extra insight into how these expressions work! Yes, my accounts can have multiple meters related to them, and my expression was only returning 1 value. Your solution returns all of them!

Thank you very much for your help. I've seen your name provide help for multiple different Arcade related questions, so I figured I'd see if you can help me, and you did!

0 Kudos
XanderBakker
Esri Esteemed Contributor

You're welcome @RyanElvrum2 , glad it works