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?
Solved! Go to Solution.
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"
);
});
}
);
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".
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?
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"
);
});
}
);
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);
});
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");