Select to view content in your preferred language

Add a button to a popup using the default contents

2175
12
Jump to solution
10-26-2023 04:50 AM
Char10773g
Emerging Contributor

Hiya, 

I'm using the latest version of the arcgis js api and cannot understand from the documentation how to set up a popupTemplate and populate it with the contents that has been configured in AGOL. The context is that I want to add a button to the popups on some layers, but not alter the popup in any other way (i.e. still display the default contents without configuring it in my application). Is this possible?

 

Thanks

0 Kudos
2 Solutions

Accepted Solutions
JoelBennett
MVP Regular Contributor

It is possible to do this if you don't mind using a bit of a hack to override the layer's createPopupTemplate method.  If you replace the contents of the script tag starting on line 29 of the Intro to FeatureLayer Sample Sandbox with the code below, and click the Refresh button at the top right, you'll see it works as described:

 

      require([
        "esri/Map",
        "esri/views/MapView",
        "esri/layers/FeatureLayer",
        "esri/core/reactiveUtils"
      ], (Map, MapView, FeatureLayer, reactiveUtils) => {
        const map = new Map({
          basemap: "hybrid"
        });

        const view = new MapView({
          container: "viewDiv",
          map: map,
          popup: {
            defaultPopupTemplateEnabled: true
          },
          extent: {
            // autocasts as new Extent()
            xmin: -9177811,
            ymin: 4247000,
            xmax: -9176791,
            ymax: 4247784,
            spatialReference: 102100
          }
        });

        /********************
         * Add feature layer
         ********************/

        // Carbon storage of trees in Warren Wilson College.
        const featureLayer = new FeatureLayer({
          url: "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Landscape_Trees/FeatureServer/0"
        });

        featureLayer._esriCreatePopupTemplate = featureLayer.createPopupTemplate;
        featureLayer.createPopupTemplate = function (options) {
          var popupTemplate = this._esriCreatePopupTemplate(options);
          popupTemplate.actions = [
            {
              title: "My Action",
              id: "my-action",
              className: "esri-icon-locate-circled"
            }
          ];

          return popupTemplate;
        };

        reactiveUtils.when(
          () => view.popup?.actions,
          () => {
            view.popup.on("trigger-action", function (evt) {
              alert(evt.action.title + " :: " + evt.action.id);
            });
          }
        );

        map.add(featureLayer);
      });

 

 

The main part of this is seen on lines 36-48 above,

View solution in original post

0 Kudos
Sage_Wall
Esri Contributor

I personally avoid using `_esriCreatePopupTemplate` and instead do something along the lines of what Rene suggested but slightly modified to add an action instead of custom content. Undocumented properties and methods may change at any time without any notification.

https://codepen.io/sagewall/pen/rNPObKK

 

 

 

            const map = new Map({
				basemap: "hybrid"
			});
			const view = new MapView({
				center: [-105, 43],
				container: "viewDiv",
				map,
				zoom: 5
			});

			const featureLayer = new FeatureLayer({
				portalItem: {
					id: "afc1428f16f94579950431add9625b43"
				}
			});
			featureLayer.load().then(() => {
				let zoomOutAction = {
					title: "Zoom out",
					id: "zoom-out",
					className: "esri-icon-zoom-out-magnifying-glass"
				};
				featureLayer.popupTemplate.actions = [zoomOutAction];
				map.add(featureLayer);
			});
			
			function zoomOut() {
				view.goTo({
					center: view.center,
					zoom: view.zoom - 2
				});
			}
			
			reactiveUtils.on(
				() => view.popup,
				"trigger-action",
				(event) => {
					if (event.action.id === "zoom-out") {
						zoomOut();
					}
				});

 

 

 

 

View solution in original post

12 Replies
JeffreyThompson2
MVP Regular Contributor

https://developers.arcgis.com/javascript/latest/api-reference/esri-PopupTemplate.html#actions

Building a button a popup requires adding an action to the PopupTemplate. See the documentation above. I'm not sure if doing so will break the default PopupTemplate or not.

GIS Developer
City of Arlington, Texas
Char10773g
Emerging Contributor

Thanks @JeffreyThompson2 ! I have managed to add the button, but I am unsure of what I need to add in the contents so that the default fields/ configuration shows without me having to define them in code. Any ideas?

0 Kudos
JeffreyThompson2
MVP Regular Contributor

Assuming you are just using a basic table for your popup, you could build a loop that grabs all the fields in your feature layer and passes a name and label in to feildInfos, as part of field type content.

https://developers.arcgis.com/javascript/latest/api-reference/esri-PopupTemplate.html#content

GIS Developer
City of Arlington, Texas
0 Kudos
Char10773g
Emerging Contributor

I'm not sure I want to display all the fields in the feature layer, but only those configured by those who publish the service from pro/ set on the layer in AGOL? Just wondering if there is any way to add a button to a popup but keep everything the same as it comes into the app so that those who manage the data can determine for each layer what fields gets shown and how, without having to interact with the application code.
I've set mapView.popup.defaultPopupTemplateEnabled to true as suggested in the content section of the PopupTemplate documentation, but the layer that I have applied my popupTemplate to with the button still opens a blank popup when I click on it.

0 Kudos
JeffreyThompson2
MVP Regular Contributor

I think the unfortunate truth is that doing anything to the PopupTemplate breaks the default popup template and makes you responsible for defining all the content.

GIS Developer
City of Arlington, Texas
0 Kudos
Char10773g
Emerging Contributor

Thanks @JeffreyThompson2 I was hoping the SDK would be more configurable than that but I fear you are right. Thanks for helping!

0 Kudos
ReneRubalcava
Honored Contributor

You can load the layer, then add your custom content to the PopupTemplate content.

https://codepen.io/odoe/pen/oNmjejJ?editors=1000

 

        featureLayer.load().then(() => {
          const customContent = new CustomContent({
            creator: () => {
              return "<div>I am custom</div>";
            }
          });
          
          featureLayer.popupTemplate.content.push(customContent);
          
          map.add(featureLayer);
        });

 

JoelBennett
MVP Regular Contributor

It is possible to do this if you don't mind using a bit of a hack to override the layer's createPopupTemplate method.  If you replace the contents of the script tag starting on line 29 of the Intro to FeatureLayer Sample Sandbox with the code below, and click the Refresh button at the top right, you'll see it works as described:

 

      require([
        "esri/Map",
        "esri/views/MapView",
        "esri/layers/FeatureLayer",
        "esri/core/reactiveUtils"
      ], (Map, MapView, FeatureLayer, reactiveUtils) => {
        const map = new Map({
          basemap: "hybrid"
        });

        const view = new MapView({
          container: "viewDiv",
          map: map,
          popup: {
            defaultPopupTemplateEnabled: true
          },
          extent: {
            // autocasts as new Extent()
            xmin: -9177811,
            ymin: 4247000,
            xmax: -9176791,
            ymax: 4247784,
            spatialReference: 102100
          }
        });

        /********************
         * Add feature layer
         ********************/

        // Carbon storage of trees in Warren Wilson College.
        const featureLayer = new FeatureLayer({
          url: "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Landscape_Trees/FeatureServer/0"
        });

        featureLayer._esriCreatePopupTemplate = featureLayer.createPopupTemplate;
        featureLayer.createPopupTemplate = function (options) {
          var popupTemplate = this._esriCreatePopupTemplate(options);
          popupTemplate.actions = [
            {
              title: "My Action",
              id: "my-action",
              className: "esri-icon-locate-circled"
            }
          ];

          return popupTemplate;
        };

        reactiveUtils.when(
          () => view.popup?.actions,
          () => {
            view.popup.on("trigger-action", function (evt) {
              alert(evt.action.title + " :: " + evt.action.id);
            });
          }
        );

        map.add(featureLayer);
      });

 

 

The main part of this is seen on lines 36-48 above,

0 Kudos
Char10773g
Emerging Contributor

Thanks very much! Great insight! Works perfectly 🙂 

0 Kudos