i created a layerlist widget as so:
this.layerList = new LayerList({
view: this.view,
selectionEnabled: true,
});
and then added it to ui.
I have bunch of featurelayers, mapimagelayers,grouplayers etc now loaded on the map.
The user rearranges the layer in the widget list as they choose fit, is it possible to find out which layer was changed?
Solved! Go to Solution.
Hi @Aeseir take a look at this codepen, hopefully it will get you started in the right direction. I wasn't sure exactly what properties on the layer you were interested in so I just used the layer title and index in the example.
require([
"esri/WebMap",
"esri/views/MapView",
"esri/core/Collection",
"esri/core/reactiveUtils",
"esri/widgets/LayerList"
], (WebMap, MapView, Collection, reactiveUtils, LayerList) => {
const changesList = document.querySelector("#changesList");
const map = new WebMap({
portalItem: {
id: "512944c00f8a4219a4bb70691089c9e9"
}
});
const view = new MapView({
container: "viewDiv",
map
});
const layerList = new LayerList({
selectionEnabled: true,
view
});
view.ui.add(layerList, "top-right");
let previousTitles = new Collection();
reactiveUtils.watch(
() => view.map.allLayers.map((layer) => layer.title),
(titles) => {
const areTitlesEqual = detectChanges(previousTitles, titles);
if (!areTitlesEqual) {
whatChanged(previousTitles, titles);
}
previousTitles = titles;
}
);
function detectChanges(
firstCollection: Collection,
secondCollection: Collection
) {
if (firstCollection.length === secondCollection.length) {
firstCollection.forEach((item, index) => {
if (item === secondCollection.getItemAt(index)) {
return true;
}
return false;
});
}
return false;
}
function whatChanged(
firstCollection: Collection,
secondCollection: Collection
) {
changesList!.innerHTML = "";
firstCollection.forEach((item, index) => {
if (item !== secondCollection.getItemAt(index)) {
const listItem = document.createElement("calcite-list-item");
listItem.label = item;
listItem.description = `previously at index ${index} moved to index ${secondCollection.findIndex(
(secondItem) => secondItem === item
)}`;
changesList!.appendChild(listItem);
}
});
}
});
Hi @Aeseir , you can use reactiveUtils to watch the map's `layers` or `alllayers` collections. We don't have an example available that shows this exact use case but the documentation shows how to watch collections and how to compare to previous values. There is also a lot of really good info in this sample. https://developers.arcgis.com/javascript/latest/sample-code/watch-for-changes-reactiveutils/ If I get time I'll try and write a codepen.
hi @Sage_Wall thanks for reaching out, that was the first place I went to see if i can figure it out, but haven't yet figured it out.
If you can find time to put together a simple codepen to show at your convenience, would be amazing.
I'll keep experimenting in meantime.
Happy to help when I can, its been really busy around here this week preparing for the 4.27 release. Hopefully I'll get a moment today to write an example
Hi @Aeseir take a look at this codepen, hopefully it will get you started in the right direction. I wasn't sure exactly what properties on the layer you were interested in so I just used the layer title and index in the example.
require([
"esri/WebMap",
"esri/views/MapView",
"esri/core/Collection",
"esri/core/reactiveUtils",
"esri/widgets/LayerList"
], (WebMap, MapView, Collection, reactiveUtils, LayerList) => {
const changesList = document.querySelector("#changesList");
const map = new WebMap({
portalItem: {
id: "512944c00f8a4219a4bb70691089c9e9"
}
});
const view = new MapView({
container: "viewDiv",
map
});
const layerList = new LayerList({
selectionEnabled: true,
view
});
view.ui.add(layerList, "top-right");
let previousTitles = new Collection();
reactiveUtils.watch(
() => view.map.allLayers.map((layer) => layer.title),
(titles) => {
const areTitlesEqual = detectChanges(previousTitles, titles);
if (!areTitlesEqual) {
whatChanged(previousTitles, titles);
}
previousTitles = titles;
}
);
function detectChanges(
firstCollection: Collection,
secondCollection: Collection
) {
if (firstCollection.length === secondCollection.length) {
firstCollection.forEach((item, index) => {
if (item === secondCollection.getItemAt(index)) {
return true;
}
return false;
});
}
return false;
}
function whatChanged(
firstCollection: Collection,
secondCollection: Collection
) {
changesList!.innerHTML = "";
firstCollection.forEach((item, index) => {
if (item !== secondCollection.getItemAt(index)) {
const listItem = document.createElement("calcite-list-item");
listItem.label = item;
listItem.description = `previously at index ${index} moved to index ${secondCollection.findIndex(
(secondItem) => secondItem === item
)}`;
changesList!.appendChild(listItem);
}
});
}
});
Thanks @Sage_Wall love your work. I ended up on something similar using a combination of reactiveUtils on list widget and all the layers. Am modifying content to adopt some of your information.
As a recommendation would be great if in future this reactivity was applied at Layer interface as a observable, thus making it event driven. It will make it easier to separate out concerns, and manage change.