Select to view content in your preferred language

Getting name of activated layer of LayerList

205
5
Jump to solution
a month ago
KaiBehncke
Occasional Contributor

Dear users,

in my application I use the LayerList Widget and an Expand-Div to place "hard-coded" legend-images:

 

 const layerList = new LayerList({
            view: view
          });
          
          
          
          const expandbutton = new Expand({
  view: view,
  content: "Legende<br>(aktuell kein Layer aktiviert)",
  label: "Legende",
  id: "legendendings",
  expandTooltip:"Legende",
  expanded:false,
  container: document.createElement("div")
});

 

E.G. if the users has actived the layer "climate" a hard-coded image like "climatelegend.png" has to be placed in the legend-container.

I wonder now: How can I  find out which layer of the LayerList is activated?

If I open the legend-Expand I would like to have that information.

I tried things like:

reactiveUtils.watch(
    () => [expandbutton.expanded], ([expandbutton]) => {
      alert ("hello: "+layerList.selectedItems.layer);
    });

...but so far I don`t get the layer-name?

 

Tags (1)
1 Solution

Accepted Solutions
Sage_Wall
Esri Contributor

Happy to help @KaiBehncke .

Your not alone it's a common question.  An item in the layer list can be selected (area 1 in your screenshot) or the visibility on the layer can be changed with the eyeball (area 2). The selection allows for things like showing a layer's properties in a different panel without affecting the visibility of the layer.  In your case, if you want to respond to a change in the visibility of the layer you have a couple options.  One of which is to create a listItemCreatedFunction and set up the watch on an individual layer's visible property.  Another way would be to watch and respond to changes directly on the layers collection, which might be better if you wanted to show the legends for all the visible layers in the map.  I created a codepen to hopefully show how this can be done.

https://codepen.io/sagewall/pen/ZEdvLmy

// Watch the selected items array for the first selected item and log it's title
    reactiveUtils.watch(
      () => layerList.selectedItems?.getItemAt(0),
      (selectedItem) => {
        console.log("Title from selectedItems:", selectedItem?.layer.title);
      }
    );

    // Create a listItemCreatedFunction and watch the list items layer.visible property
    function listItemCreatedFunction(event) {
      const { item } = event;
      const { layer } = item;

      reactiveUtils.watch(
        () => layer.visible,
        () => {
          if (layer.visible) {
            console.log(layer.title, " is visible");
          } else {
            console.log(layer.title, " is not visible");
          }
        },
        { initial: true }
      );
    }
  });

  // Watch for all the visible layers in the map and respond when one changes
  reactiveUtils.watch(
    () =>
      view.map.layers
        .filter((layer) => layer.visible)
        .map((layer) => layer.title)
        .reverse(),
    (titles) => {
      titles.forEach((title) => {
        console.log(
          "From the watch on view.map.layers: ",
          title,
          " is visible"
        );
      });
    }
  );

 

View solution in original post

0 Kudos
5 Replies
Sage_Wall
Esri Contributor

Hi @KaiBehncke 

selectedItems is a collection so you need to grab the first list item in the collection, then get the layer.

alert ("hello: "+layerList.selectedItems[0].layer.title);

Make sure you have selectionMode set to "single".

0 Kudos
KaiBehncke
Occasional Contributor

Hi Sage_Walls, thank you for answering.

Maybe I`m totally "on the wrong path".
I don`t get it to run the way you described.

I try now with:

 

const layerList = new LayerList({
            view: view,
            selectionMode: "single"
        });
    
layerList.selectedItems.on("change", ({ added, removed }) => {
alert ("hello");
alert (layerList.selectedItems[0].layer.title);
});

 

 

...but I get "Uncaught TypeError: layerList.selectedItems[0] is undefined" (you see it in the screenshot).


A thing I don`t understand at all in generally is:

I would like to get a reaction (e.g. a "hello") if I click on the eye-symbol of the layer ("area 2" of the image). But nothing at all happens.
I get a "hello", if I click in "area 1" (directly on the layer-name).

I wonder: What shall I do (with what function) to get a reaction if I click on the eye-symbol?undefined.pngselection.png

 

0 Kudos
Sage_Wall
Esri Contributor

Happy to help @KaiBehncke .

Your not alone it's a common question.  An item in the layer list can be selected (area 1 in your screenshot) or the visibility on the layer can be changed with the eyeball (area 2). The selection allows for things like showing a layer's properties in a different panel without affecting the visibility of the layer.  In your case, if you want to respond to a change in the visibility of the layer you have a couple options.  One of which is to create a listItemCreatedFunction and set up the watch on an individual layer's visible property.  Another way would be to watch and respond to changes directly on the layers collection, which might be better if you wanted to show the legends for all the visible layers in the map.  I created a codepen to hopefully show how this can be done.

https://codepen.io/sagewall/pen/ZEdvLmy

// Watch the selected items array for the first selected item and log it's title
    reactiveUtils.watch(
      () => layerList.selectedItems?.getItemAt(0),
      (selectedItem) => {
        console.log("Title from selectedItems:", selectedItem?.layer.title);
      }
    );

    // Create a listItemCreatedFunction and watch the list items layer.visible property
    function listItemCreatedFunction(event) {
      const { item } = event;
      const { layer } = item;

      reactiveUtils.watch(
        () => layer.visible,
        () => {
          if (layer.visible) {
            console.log(layer.title, " is visible");
          } else {
            console.log(layer.title, " is not visible");
          }
        },
        { initial: true }
      );
    }
  });

  // Watch for all the visible layers in the map and respond when one changes
  reactiveUtils.watch(
    () =>
      view.map.layers
        .filter((layer) => layer.visible)
        .map((layer) => layer.title)
        .reverse(),
    (titles) => {
      titles.forEach((title) => {
        console.log(
          "From the watch on view.map.layers: ",
          title,
          " is visible"
        );
      });
    }
  );

 

0 Kudos
KaiBehncke
Occasional Contributor

Thank you very much, that helped me a lot 🙂

One more solution to have a look to special layers is:

        reactiveUtils.watch(() => layer.visible, (visible) => {
          alert ("hello: "+layer.visible);
});
KaiBehncke
Occasional Contributor

Somebody might have the same problem.
With the following solution it works (with predefined images for the legend):

 

const expandbutton = new Expand({
  view: view,
  content: "Legende<br>",
  label: "Legende",
  id: "legendendings",
  expandTooltip:"Legende",
  expanded:false,
  container: document.createElement("div")
});

view.ui.add(expandbutton, "bottom-right");


function listItemCreatedFunction(event) {
      const { item } = event;
      const { layer } = item;

      reactiveUtils.watch(
        () => layer.visible,
        () => {
               var mylittlelegende = document.getElementById('legendendings_controls_content');
          if (layer.visible) {
            
 
           var pp = document.createElement("span");
           pp.setAttribute("id", layer.title);
            mylittlelegende.appendChild(pp);
            var pfadname=layer.title+"legende.png";
           
            var image = document.createElement("img");
            image.src=pfadname; 
            pp.appendChild(image);

          } else {
            var pp = document.getElementById(layer.title);
            mylittlelegende.removeChild(pp);
          }
        }
      );
    };
    
          const layerList = new LayerList({
            view: view,
            selectionMode: "single",
            listItemCreatedFunction:listItemCreatedFunction
        });
        
         view.ui.add(layerList, "bottom-left");