How to watch BasemapGalleryWidget for populating all properties

368
1
Jump to solution
02-08-2019 10:02 AM
Jay_Gregory
Regular Contributor

TLDR:

I am using a BasemapGalleryWidget in my application, which is pointed at my Portal (so all the basemaps loaded in the basemap gallery are those configured as basemaps in my Portal).  

I want to detect when not only the basemap gallery widget has populated all the basemaps, but also when the titles are populated on each basemap. 

So far I have:

let gallery = new BasemapGallery({
      container: "basemapDiv",
      view: sceneView
 });
//watch for basemaps to get populated
var handle = watchUtils.when(gallery.source.basemaps, "length", ()=>{
  //watch for names to get populated
  watchUtils.watch(gallery.source.basemaps.items[0], "title", ()=>{
    gallery.source.basemaps.items.forEach(bs=>{
    console.log(bs.title);
  });
});‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

But since each item gets it's title individually, this doesn't really work - because I assume it's a different request for each basemap to get the thumbnail, title, etc. etc.  I'm unclear how to detect on a widget when the whole thing has loaded.

Any tips?  

The longer version of my problem is this: 

I want my application to load the last basemap a user had selected for the app (I'm using local storage).  Suppose they selected a basemap from my Portal called "Colored Pencil".  So I load that string from local storage, but I can't really instantiate a Map when my app loads with 

let esriMap = new EsriMap({
  basemap: "Colored Pencil",
  ground: "world-elevation"
});

The map constructor only accepts the 12 or so "satellite", 'dark-gray", "osm", etc. etc. 

My (intended) solution to this is to wait for the BasemapGallery widget to complete loading, and programmatically select the correct basemap by the string. 

const basemap = gallery.source.basemaps.items.filter(bm=>bm.title=="Colored Pencil")[0];‍
gallery.activeBasemap = basemap;

This would hopefully just change the basemap.  Yet to be seen.  

Yet I'm stuck on watchUtils or the BasemapGalleryViewModel to let me know once the widget has completed all it's requests and populated all it's properties.  

Any tips here?

0 Kudos
1 Solution

Accepted Solutions
Jay_Gregory
Regular Contributor

To me it's kind of insane, but this is the solution I came to.  I feel like I should need to call load on each basemap, but that's what I needed to do.  It's callback hell, but it's the only way to find a basemap object based on the title.

esriConfig.portalUrl = "myportalurl";
const basemapStringToFind = "Colored Pencil"
let portal = new Portal();
portal.load().then(() => {
  portal.fetchBasemaps().then(basemaps => {
    //have to load each basemap to get the title??? otherwise the title is just "Basemap"
    let promises = [];
    basemaps.map(bm => promises.push(bm.load()));
    Promise.all(promises).then(loadedBasemaps => {
      const basemap = loadedBasemaps.filter(bm => bm.title == basemapStringToFind)[0];
      this.loadMap(basemap || "satellite");
    });
  });
});
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

View solution in original post

0 Kudos
1 Reply
Jay_Gregory
Regular Contributor

To me it's kind of insane, but this is the solution I came to.  I feel like I should need to call load on each basemap, but that's what I needed to do.  It's callback hell, but it's the only way to find a basemap object based on the title.

esriConfig.portalUrl = "myportalurl";
const basemapStringToFind = "Colored Pencil"
let portal = new Portal();
portal.load().then(() => {
  portal.fetchBasemaps().then(basemaps => {
    //have to load each basemap to get the title??? otherwise the title is just "Basemap"
    let promises = [];
    basemaps.map(bm => promises.push(bm.load()));
    Promise.all(promises).then(loadedBasemaps => {
      const basemap = loadedBasemaps.filter(bm => bm.title == basemapStringToFind)[0];
      this.loadMap(basemap || "satellite");
    });
  });
});
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos