Select to view content in your preferred language

Arcade to display attachments in popup from another layer in webmap

4779
14
Jump to solution
05-22-2023 10:33 AM
Labels (1)
BeccaSettele
Emerging Contributor

Hi, 

I have been struggling with showing attachments from one layer into another in a webmap for a bit now and am finally reaching out to the esri community blog gods.

I have two feature layers in a web map ("Beaver Obscured" and "Beaver"). I would like for the attachments in "Beaver" to show up in the popup for "Beaver Obscured". "Beaver Obscured" does not have attachments but does have a shared globalID with "Beaver". Is there a way to take the attachments from "Beaver" and add them to the popup of "Beaver Obscured" in my webmap with arcade? I thought I could do this based on their globalIDs , as I've read through several examples of how to do this with related data but I am struggling to get those scripts to work with shared globalIDs. 

Does anyone have suggestions with arcade, or other work arounds? 

Thanks in advance,
Becca

0 Kudos
1 Solution

Accepted Solutions
jcarlson
MVP Esteemed Contributor

It might look something like this:

// your other layer
var fs = FeatureSetByName($map, 'the other layer')

// get matching feature based on shared id
var match = First(Filter(fs, `shared_globalid = '${$feature['shared_globalid']}'`))

// get matching feature's attachments
var atts = Attachments(match)

// push attachment urls into array
var urls = []

for (var att in atts) {
    Push(urls, `<img src="other-layer-url/${match['objectid']}/${atts[att]['id']}"></img>`
}

return Concatenate(urls, '<br>')

Hard to say without knowing what the data looks like, but this should get you started at least.

- Josh Carlson
Kendall County GIS

View solution in original post

0 Kudos
14 Replies
jcarlson
MVP Esteemed Contributor

You can use attachments from other features / layers to generate a URL, which you can pipe into image HTML elements. Would that work for you?

- Josh Carlson
Kendall County GIS
0 Kudos
BeccaSettele
Emerging Contributor

I think that would work. I've seen the blogs on building that url (https://community.esri.com/t5/arcgis-online-blog/show-attachments-in-pop-ups-with-arcade/ba-p/890588) but am unsure on how to add the globalID element. Do you have any suggestions on incorporating globalIDs in the arcade scrip that builds the URL so that the correct photo attachments are pulled based on matching globalIDs?

Thanks for the quick reply,
Becca

0 Kudos
jcarlson
MVP Esteemed Contributor

It might look something like this:

// your other layer
var fs = FeatureSetByName($map, 'the other layer')

// get matching feature based on shared id
var match = First(Filter(fs, `shared_globalid = '${$feature['shared_globalid']}'`))

// get matching feature's attachments
var atts = Attachments(match)

// push attachment urls into array
var urls = []

for (var att in atts) {
    Push(urls, `<img src="other-layer-url/${match['objectid']}/${atts[att]['id']}"></img>`
}

return Concatenate(urls, '<br>')

Hard to say without knowing what the data looks like, but this should get you started at least.

- Josh Carlson
Kendall County GIS
0 Kudos
BeccaSettele
Emerging Contributor

Ah ok. So the aim is to:

1) access the other feature layer in the map by assigning it to fs
2) match it based on the shared globalids
3) grab the attachments from the fs
4) create and empty array and push them into there
5) finally build that url.

That makes sense. 

I'm having difficulties with the second step distinguishing between the globalid of the first layer and the attachment layer (they have the same name "globalid"). Would I need to first create a variable for the globalid in the attachment layer? I know I can access the globalid of the non-attachment layer of the popup I'm building the arcade expression in by using $feature.globalid, but am unsure how to do so for the other layer. I was unable to get your var match expression to work after changing "shared_globalid" to "globalid".

Thanks again
Becca

0 Kudos
BeccaSettele
Emerging Contributor

Scratch that. I was able to get everything running up until the URL. Can you dissect that url build any further for me? Is the idea that the url generated there matches the url of the attachment image? I'm curious as to what the [id] is referring to. 

Becca

0 Kudos
jcarlson
MVP Esteemed Contributor

Sure! Take a look at the Arcade docs: https://developers.arcgis.com/arcade/guide/types/#attachment

When we call an individual item from our array of attachments, it will have an ID. When you enable attachments on a feature service, they get their own table in your datastore, and the ID column is essentially the objectid of the attachment.

You can see this in the REST directory of a service with attachments:

jcarlson_0-1684859867781.png

Linking directly to an attachment follows the format <service-url>/<layer-index>/<objectid>/attachments/<attachmentid>

Like this:

https://maps.co.kendall.il.us/server/rest/services/Hosted/CAMA__query_/FeatureServer/0/46656/attachm...

In order to get the src tag for our HTML, we'll need the ID, as it is part of the direct URL to the file.

When that URL is piped into a popup, you get the picture!

jcarlson_1-1684860182049.png

In the expression I wrote, you'll end up with an array of <img src="the_url"> strings, and concatenating them with <br> will give you a scrollable series of images in your popup.

In order to have Arcade-generated HTML honored by the popup, you need to use an Arcade popup element, and put the result in something like this:

return { 
type : 'text',
text : Concatenate(urls, '<br>')
}
- Josh Carlson
Kendall County GIS
0 Kudos
BeccaSettele
Emerging Contributor

Josh - Thanks for detailing those components! Unfortunately, when I run this script in the Arcade </> popup element, I end up with an empty output below:

BeccaSettele_1-1684874145444.png

I had to pull out and tweak the sql portion of the filter statement in the beginning to get it to run, and now I'm wondering if that messed up how it is pulling the data from the attachment layer based on globalid. When I use a return statement for var match after line 8, the output consists of all of the attributes of one of the data points. However, using a return statement on the var atts on line 11 produces an array of 0. Do you have any thoughts on why that array would be empty? 

BeccaSettele_3-1684874710012.png

 

 

0 Kudos
BeccaSettele
Emerging Contributor

Oh my gosh, I had something selected when going into the attribute expression *face palm*. That's why it was only resulting in one gloalid. It's working great now! I can't thank you enough Josh!

0 Kudos
ZachBodenner
MVP Regular Contributor

Hi, I'm giving this a try also, and I feel like I'm very close but I'm getting an error that I don't really understand.

 

// your other layer
var fs = FeatureSetById($map, "189ffea4bbf-layer-175")

// get matching feature based on shared id
var match = First(Filter(fs, `REL_GLOBALID = '${$feature['GlobalID']}'`))

// get matching feature's attachments
var atts = Attachments(match)

// push attachment urls into array
var urls = []

for (var att in atts) {
    Push(urls, `<img src="other-layer-url/${match['ATTACHMENTID']}/${atts[att]['REL_GLOBALID']}"></img>`
}

return Concatenate(urls, '<br>')

//the default return is "Norelated forms"

 

The error message is "  ',' expected  " and it suggests that a comma belongs after the final curly bracket of the the for statement. ... Why exactly? I have gotten this a lot when testing Arcade scripts lately, but when I add a comma there it doesn't fix it.

0 Kudos