Hi there,
I need help with adding multiple custom geocoders to my web map that's based on the Public Information Template.
Problem:
I can get one of my custom geocoders to display on the map. But getting both of them to display as an option for users to select in a drop down has been a struggle.
I have tried creating a variable called "myGeocoders" that lists both geocoders and putting it in the options object below, but the map still only displayed one geocoder. In the code below, I tried listing both geocoders separately along with the ESRI geocoder to see if it will show, and it still only displayed one geocoder. Same if I take out the ESRI geocoder.
Code below:
_createGeocoderOptions: function() {
var hasEsri = false, esriIdx, geocoders = lang.clone(this.config.helperServices.geocode);
// default options
var myGeocoders = [{
url: "http://geodata.md.gov/imap/rest/services/GeocodeServices/MD_CompositeLocator/GeocodeServer",
name: "MD_CompositeLocator",
"singleLineFieldName": "SingleLine"
},{
url: "http://geodata.md.gov/imap/rest/services/GeocodeServices/MD_ParcelAccountNumberLocator/GeocodeServer",
name: "MD_ParcelAccountNumberLocator",
"singleLineFieldName": "Single Line Input"
}];
var options = {
map: this.map,
autoNavigate: true,
autoComplete: true,
arcgisGeocoder: false,
geocoders: null,
};
//only use geocoders with a url defined
geocoders = array.filter(geocoders, function (geocoder) {
if (geocoder.url) {
return true;
}
else{
return false;
}
});
// at least 1 geocoder defined
if(geocoders.length){
// each geocoder
array.forEach(geocoders, lang.hitch(this, function(geocoder) {
// if esri geocoder
if (geocoder.url && geocoder.url.indexOf(".arcgis.com/arcgis/rest/services/World/GeocodeServer") > -1) {
hasEsri = true;
geocoder.name = "Esri World Geocoder";
geocoder.outFields = "Match_addr, stAddr, City";
geocoder.singleLineFieldName = "Single Line";
geocoder.esri = true;
geocoder.placefinding = true;
geocoder.placeholder = this.config.i18n.general.find;
}
//if not esri geocoder
if (geocoder.url && geocoder.url.indexOf("http://geodata.md.gov/imap/rest/services/GeocodeServices/MD_CompositeLocator/GeocodeServer") > -2) {
hasEsri = false;
geocoder.name = "MD_CompositeLocator";
geocoder.outFields = "Street, City, State, ZIP";
geocoder.singleLineFieldName = "SingleLine";
geocoder.esri = false;
geocoder.placefinding = true;
geocoder.placeholder = "Find a Place";
}
//if not esri geocoder
if (geocoder.url && geocoder.url.indexOf("http://geodata.md.gov/imap/rest/services/GeocodeServices/MD_ParcelAccountNumberLocator/GeocodeServer") > -1) {
hasEsri = false;
geocoder.name = "MD_ParcelAccountNumberLocator";
geocoder.outFields = "*";
geocoder.singleLineFieldName = "Single Line Input";
geocoder.esri = false;
geocoder.placefinding = true;
geocoder.placeholder = "Find a Parcel Point Account ID";
}
})) ;
//only use geocoders with a singleLineFieldName that allow placefinding unless its custom
geocoders = array.filter(geocoders, function (geocoder) {
if (geocoder.name && geocoder.name === "Custom") {
return (esriLang.isDefined(geocoder.singleLineFieldName));
} else {
return (esriLang.isDefined(geocoder.singleLineFieldName) && esriLang.isDefined(geocoder.placefinding) && geocoder.placefinding);
}
});
// if we have an esri geocoder
if (hasEsri) {
for (var i = 0; i < geocoders.length; i++) {
if (esriLang.isDefined(geocoders.esri) && geocoders.esri === true) {
esriIdx = i;
break;
}
}
}
// set autoComplete
options.autoComplete = true;
// set esri options
if (hasEsri) {
options.minCharacters = 0;
options.maxLocations = 5;
options.searchDelay = 100;
}
//If the World geocoder is primary enable auto complete
if (hasEsri && esriIdx === 0) {
options.arcgisGeocoder = geocoders.splice(0, 1)[0]; //geocoders[0];
if (geocoders.length > 0) {
options.geocoders = geocoders;
}
} else {
options.arcgisGeocoder = false;
options.geocoders = geocoders;
}
}
return options;
},
// create geocoder widgets
_createGeocoders: function () {
//add geocoder result layer
var resultsLayer = new esri.layers.GraphicsLayer({ id: "resultsLayer" }); //geocoder symbol code
this.map.addLayer(resultsLayer);
// get options
var createdOptions = this._createGeocoderOptions();
// desktop geocoder options
var desktopOptions = lang.mixin({}, createdOptions, {
theme: this.css.desktopGeocoderTheme
});
// mobile geocoder options
var mobileOptions = lang.mixin({}, createdOptions, {
theme: this.css.mobileGeocoderTheme
});
// desktop size geocoder
this._geocoder = new Geocoder(desktopOptions, dom.byId("geocoderSearch"));
;
this._geocoder.startup();
//add feature to map //geocoder symbol
function addFeatureToMap(geometry) {
resultsLayer.clear();
var pictureMarkerSymbol = new PictureMarkerSymbol({ "angle": 0, "xoffset": 2, "yoffset": 8, "type": "esriPMS", "url": "http://static.arcgis.com/images/Symbols/Basic/RedStickpin.png", "contentType": "image/png", "width": 24, "height": 24 });
resultsLayer.add(new Graphic(geometry, pictureMarkerSymbol));
}
//zoom to level 19 after press geocoder - MIO
on(this._geocoder, 'select', lang.hitch(this, function (response) {
console.log("set zoom function");
console.log(this.map);
this.map.setZoom(19);
}));
// geocoder results
on(this._geocoder, 'find-results', lang.hitch(this, function (response) {
if (!response.results || !response.results.results || !response.results.results.length) {
alert(this.config.i18n.general.noSearchResult);
} else { //geocoder symbol results
addFeatureToMap(response.results.results[0].feature.geometry);
if (history.pushState) {
//browser supported.
//refresh the URL with the geocoder result
console.log("Push state is supported. Geocoder result: ");
console.log(this._geocoder.value);
window.history.pushState(null,null,"?address=" + this._geocoder.value);
}
}
}));
// mobile sized geocoder
this._mobileGeocoder = new Geocoder(mobileOptions, dom.byId("geocoderMobile"));
this._mobileGeocoder.startup();
// geocoder results
on(this._mobileGeocoder, 'find-results', lang.hitch(this, function (response) {
if (!response.results || !response.results.results || !response.results.results.length) {
alert(this.config.i18n.general.noSearchResult);
} else { //geocoder symbol results and all below until keep geocoder values in sync
addFeatureToMap(response.results.results[0].feature.geometry);
//refresh the URL with the geocoder result
if (history.pushState) {
//browser supported.
//refresh the URL with the geocoder result
console.log("Push state is supported. Geocoder result: ");
console.log(this._geocoder.value);
window.history.pushState(null,null,"?address=" + this._geocoder.value);
}
}
this._hideMobileGeocoder();
}));
on(this._geocoder, 'clear', lang.hitch(this, function () {
resultsLayer.clear();
})); //rest of geocoder symbol result
on(this._mobileGeocoder, 'clear', lang.hitch(this, function () {
resultsLayer.clear();
})); //rest of geocoder symbol result
// keep geocoder values in sync
this._geocoder.watch("value", lang.hitch(this, function () {
var value = arguments[2];
this._mobileGeocoder.set("value", value);
}));
// keep geocoder values in sync
this._mobileGeocoder.watch("value", lang.hitch(this, function () {
var value = arguments[2];
this._geocoder.set("value", value);
}));
// geocoder nodes
this._mobileGeocoderIconNode = dom.byId("mobileGeocoderIcon");
this._mobileSearchNode = dom.byId("mobileSearch");
this._mobileGeocoderIconContainerNode = dom.byId("mobileGeocoderIconContainer");
// mobile geocoder toggle
if (this._mobileGeocoderIconNode) {
on(this._mobileGeocoderIconNode, "click", lang.hitch(this, function () {
if (domStyle.get(this._mobileSearchNode, "display") === "none") {
this._showMobileGeocoder();
} else {
this._hideMobileGeocoder();
}
}));
}
var closeMobileGeocoderNode = dom.byId("btnCloseGeocoder");
if(closeMobileGeocoderNode){
// cancel mobile geocoder
on(closeMobileGeocoderNode, "click", lang.hitch(this, function () {
this._hideMobileGeocoder();
}));
}
},Background Info:
Level: newbie JS developer.
Using ESRI JavaScript API - ESRI's Public information web map template: Esri/public-information-map-template-js · GitHub
This code was added to the main.js file in the _init: function ().
Any tips?
Thanks.
Solved! Go to Solution.
Instead of defining your geocoders in the main.js file try adding them to defaults. js instead. If you open defaults.js in a text editor you'll see there's a section for helper services and it contains a place where you can define one or more geocode services. Here's an example of customizing it for your services:
"geocode": [{
"url": "http://geodata.md.gov/imap/rest/services/GeocodeServices/MD_CompositeLocator/GeocodeServer",
"singleLineFieldName": "SingleLine",
"name": "MD_CompositeLocator",
"placefinding":true,
"placeholder": "Find a place"
},{
"url":"http://geodata.md.gov/imap/rest/services/GeocodeServices/MD_ParcelAccountNumberLocator/GeocodeServer",
"singleLineFieldName": "SingleLine",
"name": "MD_ParcelAccountNumberLocator",
"placefinding":true,
"placeholder": "Find a Parcel Point Account ID"
}]After defining your services open the templateConfig.js file and set the queryForOrg option to false so that it doesn't query ArcGIS Online for helper services and uses the ones you've defined in default. js.
Instead of defining your geocoders in the main.js file try adding them to defaults. js instead. If you open defaults.js in a text editor you'll see there's a section for helper services and it contains a place where you can define one or more geocode services. Here's an example of customizing it for your services:
"geocode": [{
"url": "http://geodata.md.gov/imap/rest/services/GeocodeServices/MD_CompositeLocator/GeocodeServer",
"singleLineFieldName": "SingleLine",
"name": "MD_CompositeLocator",
"placefinding":true,
"placeholder": "Find a place"
},{
"url":"http://geodata.md.gov/imap/rest/services/GeocodeServices/MD_ParcelAccountNumberLocator/GeocodeServer",
"singleLineFieldName": "SingleLine",
"name": "MD_ParcelAccountNumberLocator",
"placefinding":true,
"placeholder": "Find a Parcel Point Account ID"
}]After defining your services open the templateConfig.js file and set the queryForOrg option to false so that it doesn't query ArcGIS Online for helper services and uses the ones you've defined in default. js.
So simple! Wow. Thanks!