I have created a simple widget for use in Web AppBuilder for Developers 2.15. The widget provides the user a list of layers to add to the map (currently containing one layer). The layer in question is a feature layer that contains urls to kml files provided in a field in the attribute table. What I am trying to accomplish is to have the user click on a feature and get a popup box describing the feature and also a button to load the kml into the map. The user can then click the button to load the KML into the map if desired. It's all working splendidly, except the kml is loading when the feature is selected rather than when Load KML button is clicked. Does anyone have a suggestion on how I might fix this?
define([
'dojo/_base/declare',
'jimu/BaseWidget',
'jimu/loaderplugins/jquery-loader!https://code.jquery.com/jquery-git1.min.js',
'jimu/WidgetManager',
'jimu/PanelManager',
'esri/map',
'esri/layers/ArcGISDynamicMapServiceLayer',
'esri/layers/KMLLayer',
'esri/dijit/Popup',
'esri/dijit/PopupTemplate',
'dojo/dom-construct',
'dojo/query',
'dojo/_base/array',
'dojo/dom',
'dojo/parser',
'dojo/ready',
'dojo/on'
],
function(
declare,
BaseWidget,
$,
WidgetManager,
PanelManager,
map,
ArcGISDynamicMapServiceLayer,
KMLLayer,
Popup,
PopupTemplate,
domConstruct,
query,
arrayUtils,
dom,
parser,
ready,
on
) {
//To create a widget, you need to derive from BaseWidget.
return declare([BaseWidget], {
baseClass: 'jimu-widget-kmlloader',
postCreate: function() {
this.inherited(arguments);
console.log('postCreate');
},
startup: function() {
this.inherited(arguments);
//establish the map object
var map = this.map;
//here's what happens if the 'load data' button is clicked
$('.jimu-widget-use-jquery .dataloader').click(function(){
var lyrCnt = 0;
var myLyrList = [];
if (document.getElementById("chb_coastSurvs").checked == true) {
lyrCnt++;
myLyrList.push("coastSurvs");
}
if (lyrCnt == 0) {
alert("Please choose the layers you wish to add to the map.");
} else {
document.getElementById("btn_datadestroyer").disabled = false;
document.getElementById("btn_dataloader").disabled = true;
loadLAData(myLyrList);
}
});
//This functio loads the layers the user has selected
function loadLAData(myLyrs) {
if (myLyrs.includes("coastSurvs")) {
console.log("Loading Coast Surveys");
var coastSurvsLyr = new ArcGISDynamicMapServiceLayer("https://data.myserver.com/arcgis/rest/services/base/NOAACoastalSurveys/MapServer", {
visible: true,
id: 'la_coastSurvs',
});
//Here's a pop-up template for the index layer
console.log("setting up popup templates");
//Set up button to load kml
var kmlBtn = dojo.create("button", {
"id": "kmlButton",
"class": "action",
"innerHTML": "Load KML",
}, dojo.query(".actionList", map.infoWindow.domNode)[0]);
//when the button is clicked register a function that will run
on(kmlBtn, "click", loadKML());
var templateCoastSurv = new PopupTemplate({
title: "{surv_code}",
description: "<p>Description: {surv_desc}</p>" +
"<p>Date: {surv_date}</p>" +
"<p>Scale: {surv_scale}</p>" +
"<p><a href='{kml_prev}'>KML Preview</a></p>",
fieldInfos: [
{fieldName: "surv_code", visible: true},
{fieldName: "surv_desc", visible: true},
{fieldName: "surv_date", visible: true, digitSeparator: false},
{fieldName: "surv_scale", visible: true, digitSeparator: true},
{fieldName: "kml_prev", visible: true}
]
});
coastSurvsLyr.setInfoTemplates({
0: {infoTemplate: templateCoastSurv},
});
map.addLayer(coastSurvsLyr);
}
}
//This function will use a url stored in the attribute to load a kml into the map
function loadKML() {
console.log("Entered loadKMLs function");
map.infoWindow.on("selection-change", function() {
var selectedFeature = map.infoWindow.getSelectedFeature();
if (selectedFeature && selectedFeature.attributes.kml_prev.includes("http")) {
console.log(selectedFeature.attributes.kml_prev);
var kmlUrl = selectedFeature.attributes.kml_prev;
var kml = new KMLLayer(kmlUrl, {
id: "la_" + kmlUrl.substring(kmlUrl.lastIndexOf('/') + 1)
});
map.addLayer(kml);
kml.on("load", function() {
domStyle.set("loading", "display", "none");
});
}
});
}
//here's what happens if the 'clear data' button is clicked
$('.jimu-widget-use-jquery .datadestroyer').click(function(){
//remove all temporary layers from the map
lyrsToRemove = [];
for (var lyrID of map.layerIds) {
if (lyrID.includes("la_") == true) {
console.log("remove " + lyrID);
lyrsToRemove.push(lyrID);
}
}
for (var lyrName of lyrsToRemove) {
var myLyr = map.getLayer(lyrName);
if (myLyr) {
map.removeLayer(myLyr);
}
}
//clean up the html elements
document.getElementById("chb_coastSurvs").checked = false;
document.getElementById("btn_datadestroyer").disabled = true;
document.getElementById("btn_dataloader").disabled = false;
});
}
});
});
Solved! Go to Solution.
Shannon,
This line is the problem.
on(kmlBtn, "click", loadKML());
//the loadKML() cause the code to call the function imediately
//when the code is parsed.
on(kmlBtn, "click", loadKML);
//this is the correct way.
Shannon,
This line is the problem.
on(kmlBtn, "click", loadKML());
//the loadKML() cause the code to call the function imediately
//when the code is parsed.
on(kmlBtn, "click", loadKML);
//this is the correct way.
Thank you Robert! You put me on the right track. I also had to remove the selection-change trigger from my LoadKML function and that did the trick.
//This function will use a url stored in the attribute to load a kml into the map
function loadKML() {
console.log("Entered loadKMLs function");
//map.infoWindow.on("selection-change", function() {
var selectedFeature = map.infoWindow.getSelectedFeature();
if (selectedFeature && selectedFeature.attributes.kml_prev.includes("http")) {
console.log(selectedFeature.attributes.kml_prev);
var kmlUrl = selectedFeature.attributes.kml_prev;
var kml = new KMLLayer(kmlUrl, {
id: "la_" + kmlUrl.substring(kmlUrl.lastIndexOf('/') + 1)
});
map.addLayer(kml);
kml.on("load", function() {
domStyle.set("loading", "display", "none");
});
}
//});
}