2

EDIT: Actually this posted link ended up helping me quite a bit but don't mark it as duplicate because the problem I had using it stemmed from needing to define the map before defining the basemapGallery. See ADDENDUM below.

Note that this post does NOT help me ... How do I use the Terrain with Labels basemap in the Map constructor

I am using PHP and trying to pass in this variable (among others) representing the basemap id "basemap_5" to determine the selected basemap when a new page is "launched" (basically my page launches a new map with the same center (XY) and zoom level).

Then using $_GET I can access the php variable in my javascript to determine which basemap was being viewed and use those variables like this ...

map = new Map("map", {
basemap: bMapName,
center: passedCenter,
zoom: zoomLevel

});

I added a new argument for the basemap (as shown above ... "bMapName") and they all work except this one (basemap_5 aka Terrain with Labels). The error I get is ...

Map.setBasemap: Unable to find basemap definition for: "Terrain with Labels". Try one of these: streets,satellite,hybrid,topo,gray,oceans,national-geographic,osm

I sure wish the error message were updated to include the terrain with labels map!

I also tried "World Terrain Base" since that appears to be the name of the service Link to Service

EDIT: Let me add to this that I'm using the BasemapGallery widget. The problem centers around needing to identify the basemap before creating the basemapGallery (which has "map" set for it's map property). If I can just get around that, I think I could get this to work. I have tried the samples below and from the post I linked to above. I can add custom maps but they aren't recognized (obviously) before they have been added. So how can I get around that?

    map = new Map("map", {
    basemap: bMapName,
    center: passedCenter,
    zoom: zoomLevel
  });

  //add the basemap gallery, in this case we'll display maps from ArcGIS.com including bing maps
  basemapGallery = new BasemapGallery({
    showArcGISBasemaps: true,
    map: map
  }, "basemapGallery");

ADDENDUM I got this to work by defining "map" conditionally and setting the basemap property to a created basemap (as in the posted link) in the condition that one of the two maps that weren't working (my custom basemap and the "Terrain with Labels" basemap) were the ones being referenced "over the wire". setting the basemap property as shown in the linked SE post was actually the most helpful part of this but the answer provided here was similarly helpful.

  switch (bMap) {
  case "basemap_0":
    bMapName = "MD Imagery";
    break;
  case "basemap_1":
    bMapName = "osm";
    break;
  // SEVERAL MORE CASES HERE; TRUNCATED FOR SE POST ...
  }
mdImagelayer = new ArcGISTiledMapServiceLayer("http://geodata.md.gov/imap/rest/services/Imagery/MD_SixInchImagery/MapServer");
  if (bMapName === "terrain") {
    map = new Map("map", {
      basemap: new Basemap({id: 'terrain',
                  layers: [new BasemapLayer({url: 'http://services.arcgisonline.com/arcgis/rest/services/World_Terrain_Base/MapServer'}),
                    new BasemapLayer({url: 'http://services.arcgisonline.com/ArcGIS/rest/services/Reference/World_Reference_Overlay/MapServer'})
                  ]
            }), 
      center: passedCenter, // [-79.2, 39.5]
      zoom: zoomLevel // 12
    });
  } else if (bMapName === "MD Imagery") {  
    map = new Map("map", {
      basemap: new Basemap({id: 'MD Imagery', layers: [mdImagelayer]}), 
      center: passedCenter, // [-79.2, 39.5]
      zoom: zoomLevel // 12
    });
  } else {
  // You may wish to change the id to map or mapDiv (if that is the map you are using
    map = new Map("map", {
      basemap: bMapName,
      center: passedCenter, // [-79.2, 39.5]
      zoom: zoomLevel // 12
    });
  };

  //add the basemap gallery, in this case we'll display maps from ArcGIS.com including bing maps
  basemapGallery = new BasemapGallery({
    showArcGISBasemaps: true,
    map: map
  }, "basemapGallery");
2
  • Can you clarify what it is about my answer in the linked post did not work for you? The options provided in the updated answer of adding to the basemaps object sounds like it fits your requirements.
    – tmcgee
    Sep 24, 2014 at 6:16
  • I've attempted to clarify what is not working for me. Sep 24, 2014 at 17:09

2 Answers 2

3

As @tmcgee points out in the linked answer, the list of basic base maps that can be passed to the constructor are set in the esriConfig defaults object. It's not that the error message needs to be updated, it's that the constructor can only be passed a value in this list and that doesn't include an entry for the Terrain with Labels basemap.

I've handled this by checking the specified base map and if it's not one of the ones the constructor is aware of, I create the map without a basemap and then follow it with an addLayer and add the required basemap using it's URL. This then works for non-ESRI base maps such as those we serve ourselves.

However, the solution in the linked answer by @tmcgee (the bit after the update) is much better and I think I might have to update my application to do it this way. Basically you are making the constructor aware of additional basemaps, be they other ESRI provided ones or your own, so the name of the basemap can be passed to the constructor as normal.

I wonder if the reason this approach didn't work for you is that the example code shows creating a new basemap as a property of the basemaps object called 'terrain'. However, the value being passed to the constructor from your PHP variable is "Terrain with Labels". I presume this is being generated from the Basemap Gallery or something like that. I can think of two ways of solving this:

  1. Create a new basemap as a property called terrain. In your PHP code, check the value of the bMapName property and if it is "Terrain with Labels", change it to "terrain". The value then passed to the map constructor should be "terrain" and it should therefore match the new basemap that you added.

  2. Instead of creating the new basemap as a property called "terrain", actually call the property "Terrain with Labels". JavaScript allows object properties to have spaces, you just need to access them in a similar way to an array index (e.g. like an associative array). To do this, change the code that creates the new basemap property to:

    esriConfig.defaults.map.basemaps["Terrain with Labels"] = {
        baseMapLayers: [
          {
            url: "http://services.arcgisonline.com/arcgis/rest/services/World_Terrain_Base/MapServer"
          }, 
          {
            url: "http://services.arcgisonline.com/ArcGIS/rest/services/Reference/World_Reference_Overlay/MapServer"
          } 
        ],
        title: "Terrain Basemap"
      };

Admittedly I haven't tried either approach but from what you've described, I think either of these should work.

@tmcgee, good work putting together your answer. How do I use the Terrain with Labels basemap in the Map constructor

2
  • Another thing about this is that my definition of the map comes before my definition of the basemapGallery and the PHP variables get parsed at the very top of the page, so using my bMapName variable in the process of defining the map (as in my code snippet in the question) doesn't work bc it expects "Terrain with Labels" to mean something before it has been defined. I experimented with trying to define the basemaps before defining the map but it didn't go very well. Sep 24, 2014 at 16:34
  • I think the problem I'm having with this is the basemap ("Terrain with Labels") is already in the list of basemaps (from the BasemapGallery), so what is this code actually doing? Is it going to replace the existing basemap somehow? I can add it in as is done in @tmcgee's sample but it seems I'll have to take it out of the BasemapGallery. Not having it not in the "esriConfig defaults object" seems wrong to me since I got it from the BasemapGallery widget as is (not that I can do anything about that). I have added my own basemaps to the gallery as well and they work fine! Sep 24, 2014 at 16:52
2

Glad you got it sorted out. It is worth clarifying that the basemaps from the BasemapGallery have no relationship to the basemap ids of the map object. The mechanics as I understand them are as follows:

  1. The widget retrieves the basemaps it uses from ArcGIS Online from a specific map group. First it searches for the group based on title/owner:

http://www.arcgis.com/sharing/rest/community/groups?q=title%3A%22ArcGIS%20Online%20Basemaps%22%20AND%20owner%3Aesri_en&f=json

  1. Then it retrieves the maps for that group:

http://www.arcgis.com/sharing/rest/search?q=group%3A1f3bd43413f14b219643db9ae040423c%20AND%20type%3A%22web%20map%22&sortField=name&sortOrder=desc&num=50&f=json

It then iterates through those maps to populate the gallery. After the widget loads, you can select one of those basemaps:

basemapGallery.on("load", function(){
    basemapGallery.select('basemap_4');
});

This could be used as possible alternative that might result in less code and less code is always good ;).

Note that there is no guarantee that an id of basemap_4 or basemap_5 will always represent the same map. It appears those ids are dynamically created as the BasemapGallery widget iterates through the maps it retrieves from the second url above. You can loop through the widget's basemaps array to get the id matching the title Terrain with Labels.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.