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
Solved! Go to Solution.
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,
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();
}
});
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.
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?
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
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.
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.
Thanks @JeffreyThompson2 I was hoping the SDK would be more configurable than that but I fear you are right. Thanks for helping!
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);
});
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,
Thanks very much! Great insight! Works perfectly 🙂