Smart Forms Field Calculator Domain from Nearby

741
6
Jump to solution
09-06-2023 09:26 AM
HMarcks
New Contributor III

Hello All,

I am working on a version of 

7. Store info about a nearby feature

from this blog

https://www.esri.com/arcgis-blog/products/field-maps/field-mobility/common-calculated-expressions-fo...

In my version I need to 1) look at multiple layers and 2) get the DomainName as opposed to the stored number value.  I have figured out how to get #1 done but I cannot figure out how to get the domain name description and have tried out various scenarios with no luck.

The worst part is I did have this working at one point and removed and re-added the layer the form was built on because it was acting funny, not realizing I would loose the form completely.  I just cannot recall how I did it.  So if anyone can help me out or point me in the right direction I would really appreciate it.

 

// If feature doesn't have geometry return null
if (IsEmpty(Geometry($feature))) { return null }

// Get the Possible leaking assets layers
var Mains = FeatureSetByName($map, "WaterDistributionSystem_viewing - Water Main")
var Services = FeatureSetByName($map, "WaterDistributionSystem_viewing - Service")


// Buffer the current location and intersect with Features
var bufferedLocation = Buffer($feature, 30, 'feet')
var candidateMains = Intersects(Mains, bufferedLocation)
var candidateServices = Intersects(Services, bufferedLocation)

// Calculate the distance between the Feature and the current location
// Store the feature and distance as a dictionary and push it into an array
var featuresWithDistances = []
for (var f in candidateMains) {
    Push(featuresWithDistances, 
        {
            'distance': Distance($feature, f, 'feet'),
            'feature': f
        }
    )
}

for (var f in candidateServices) {
    Push(featuresWithDistances, 
        {
            'distance': Distance($feature, f, 'feet'),
            'feature': f
        }
    )
}

// Sort the candidates of closest features by distance using a custom function
function sortByDistance(a, b) {
    return a['distance'] - b['distance']
}
var sorted = Sort(featuresWithDistances, sortByDistance)

// Get the closest feature
var closestFeatureWithDistance = First(sorted)

// If there was no feature, return null
if (IsEmpty(closestFeatureWithDistance)) { return null }

// Return the AssetType

var Facility =  DomainName(closestFeatureWithDistance, ['assettype'])

return Facility

 

 

0 Kudos
1 Solution

Accepted Solutions
HMarcks
New Contributor III

I ended up just taking the domain coded value and using nested iif statements to convert it to the name/description.  This is not pretty, not convenient if you have a lot of domains to convert and I am sure there is a better way.  So if anyone comes across this and can enlighten me I would be happy to see it.

 

// If feature doesn't have geometry return null
if (IsEmpty(Geometry($feature))) { return null }

// Get the Possible leaking assets layers
var Mains = FeatureSetByName($map, "Water Main")
var Services = FeatureSetByName($map, "Service")


// Buffer the current location and intersect with Features
var bufferedLocation = Buffer($feature, 30, 'feet')
var candidateMains = Intersects(Mains, bufferedLocation)
var candidateServices = Intersects(Services, bufferedLocation)

// Calculate the distance between the Feature and the current location
// Store the feature and distance as a dictionary and push it into an array
var featuresWithDistances = []
for (var f in candidateMains) {
    Push(featuresWithDistances, 
        {
            'distance': Distance($feature, f, 'feet'),
            'feature': f
        }
    )
}

for (var f in candidateServices) {
    Push(featuresWithDistances, 
        {
            'distance': Distance($feature, f, 'feet'),
            'feature': f
        }
    )
}

// Sort the candidate Mains by distance using a custom function
function sortByDistance(a, b) {
    return a['distance'] - b['distance']
}
var sorted = Sort(featuresWithDistances, sortByDistance)

// Get the closest feature
var closestFeatureWithDistance = First(sorted)

// If there was no feature, return null
if (IsEmpty(closestFeatureWithDistance)) { return null }

// Get the Asset Type Code Number
var AssetTypeCode = closestFeatureWithDistance['feature']['AssetType']

// Convert asset type codde number to domain name/description and return
Var AssetName = IIf(AssetTypeCode == 0, 'Unknown',
IIf(AssetTypeCode == 1, 'Transmission Main',
IIf(AssetTypeCode == 2, 'Distribution Main',
IIf(AssetTypeCode == 3, 'Production',
IIf(AssetTypeCode == 4, 'Drain',
IIf(AssetTypeCode == 5, 'Overflow',
IIf(AssetTypeCode == 11, 'Residential Service',
IIf(AssetTypeCode == 12, 'Commercial Service',
IIf(AssetTypeCode == 13, 'Industrial Service',
IIf(AssetTypeCode == 14, 'Fire Service',
IIf(AssetTypeCode == 15, 'Hydrant Service',
IIf(AssetTypeCode == 16, 'Irrigation Service',
IIf(AssetTypeCode == 17, 'Sampling Service',
IIf(AssetTypeCode == 18, 'Blow Off Service',
IIf(AssetTypeCode == 19, 'Air and Vacuum Service', null)))))))))))))))

return AssetName

 

 

View solution in original post

0 Kudos
6 Replies
HMarcks
New Contributor III

I still can't figure this out.  I swear before when I figured it out I found a sample code that had something to do with "Pole Types."  I cant get it to give me the domain code but can't get it to return the domain name, I don't know why all my different ways of using DomainName wont work.

This returns the Domain Code:

// If feature doesn't have geometry return null
if (IsEmpty(Geometry($feature))) { return null }

// Get the Possible leaking assets layers
var Mains = FeatureSetByName($map, "Water Main")
var Services = FeatureSetByName($map, "Service")


// Buffer the current location and intersect with Features
var bufferedLocation = Buffer($feature, 30, 'feet')
var candidateMains = Intersects(Mains, bufferedLocation)
var candidateServices = Intersects(Services, bufferedLocation)

// Calculate the distance between the Feature and the current location
// Store the feature and distance as a dictionary and push it into an array
var featuresWithDistances = []
for (var f in candidateMains) {
    Push(featuresWithDistances, 
        {
            'distance': Distance($feature, f, 'feet'),
            'feature': f
        }
    )
}

for (var f in candidateServices) {
    Push(featuresWithDistances, 
        {
            'distance': Distance($feature, f, 'feet'),
            'feature': f
        }
    )
}

// Sort the candidate Mains by distance using a custom function
function sortByDistance(a, b) {
    return a['distance'] - b['distance']
}
var sorted = Sort(featuresWithDistances, sortByDistance)

// Get the closest feature
var closestFeatureWithDistance = First(sorted)

// If there was no feature, return null
if (IsEmpty(closestFeatureWithDistance)) { return null }

// Return the AssetID
return `${closestFeatureWithDistance['feature']['AssetType']}`

 

Any version of this just give me an error and doesn't calculate:

DomainName(closestFeatureWithDistance, 'assettype')

DomainName (FeatureSetByName($map, closestFeatureWithDistance),'assetype')

 

0 Kudos
BenjaminSegal
Esri Contributor

Hello @HMarcks,

I noticed when attempting to return the DomainName you are using assettype as the attribute parameter with no capital letters, and when you're successfully returning the domain code you are using AssetType with capital letters. I wonder if the issue is related to that? 

Thanks,

Ben Segal 

 

0 Kudos
HMarcks
New Contributor III

Thanks for the suggestion, the field name (not the alias) is actually lower case and returns the domain code whether I use lower case or upper case.  I did go ahead and try to get the domain name using upppercase and I still got an error.

Should I be able to use my variable closestFeatureWithDistance as the layer name/inputFeature for the domain function?  And I am just not using it correctly.

I feel like I went a different route the first time I did it and got it to work.  Like I had it return an array of the domains first then had it pull the correct one based on the nearest feature... maybe, idk.

0 Kudos
HMarcks
New Contributor III

So I just noticed something that may be key to this.  When creating the Arcade if I go into the current layer $feature layer and go to a field with a domain it gives me an option to just choose the DomainName function already filled in.  It does not have that available when I go to the $map variables.  This makes me think I cannot get the domain from a map variable directly.  I must of figured out some work around, maybe something to do with relationships.🤔

$Feature with DomainName available$Feature with DomainName available$Feature$Feature$Map no DomainName available$Map no DomainName available$Map$Map

0 Kudos
HMarcks
New Contributor III

I just posted a link to this in the general Community message board hoping to get some attention to it since it has more to do with Arcade than Field Maps.  Here is a link back to that post in case answers show up there instead.

https://community.esri.com/t5/community-feedback/arcade-smart-forms-field-calculator-domain-from/m-p...

0 Kudos
HMarcks
New Contributor III

I ended up just taking the domain coded value and using nested iif statements to convert it to the name/description.  This is not pretty, not convenient if you have a lot of domains to convert and I am sure there is a better way.  So if anyone comes across this and can enlighten me I would be happy to see it.

 

// If feature doesn't have geometry return null
if (IsEmpty(Geometry($feature))) { return null }

// Get the Possible leaking assets layers
var Mains = FeatureSetByName($map, "Water Main")
var Services = FeatureSetByName($map, "Service")


// Buffer the current location and intersect with Features
var bufferedLocation = Buffer($feature, 30, 'feet')
var candidateMains = Intersects(Mains, bufferedLocation)
var candidateServices = Intersects(Services, bufferedLocation)

// Calculate the distance between the Feature and the current location
// Store the feature and distance as a dictionary and push it into an array
var featuresWithDistances = []
for (var f in candidateMains) {
    Push(featuresWithDistances, 
        {
            'distance': Distance($feature, f, 'feet'),
            'feature': f
        }
    )
}

for (var f in candidateServices) {
    Push(featuresWithDistances, 
        {
            'distance': Distance($feature, f, 'feet'),
            'feature': f
        }
    )
}

// Sort the candidate Mains by distance using a custom function
function sortByDistance(a, b) {
    return a['distance'] - b['distance']
}
var sorted = Sort(featuresWithDistances, sortByDistance)

// Get the closest feature
var closestFeatureWithDistance = First(sorted)

// If there was no feature, return null
if (IsEmpty(closestFeatureWithDistance)) { return null }

// Get the Asset Type Code Number
var AssetTypeCode = closestFeatureWithDistance['feature']['AssetType']

// Convert asset type codde number to domain name/description and return
Var AssetName = IIf(AssetTypeCode == 0, 'Unknown',
IIf(AssetTypeCode == 1, 'Transmission Main',
IIf(AssetTypeCode == 2, 'Distribution Main',
IIf(AssetTypeCode == 3, 'Production',
IIf(AssetTypeCode == 4, 'Drain',
IIf(AssetTypeCode == 5, 'Overflow',
IIf(AssetTypeCode == 11, 'Residential Service',
IIf(AssetTypeCode == 12, 'Commercial Service',
IIf(AssetTypeCode == 13, 'Industrial Service',
IIf(AssetTypeCode == 14, 'Fire Service',
IIf(AssetTypeCode == 15, 'Hydrant Service',
IIf(AssetTypeCode == 16, 'Irrigation Service',
IIf(AssetTypeCode == 17, 'Sampling Service',
IIf(AssetTypeCode == 18, 'Blow Off Service',
IIf(AssetTypeCode == 19, 'Air and Vacuum Service', null)))))))))))))))

return AssetName

 

 

0 Kudos