Looking for any examples of a collapsible layer list that Auto fills with my layers.
I have seen some really basic layer list examples on the api page but nothing that allows collapsible areas and auto filling of your layers.
I am trying to create 3 different areas as seen below. Were the box next to the ------------- would collapse that section.
But I want it to auto fill the layers from my .js page.
Right now I am adding layers to the list and adding check boxes BUT THERE it is not collapsible
legendLayers.push({ layer: FloodZonelayer, title: 'Flood Zones' });
// ADD CHECK BOXES FOR LAYERS
map.on('layers-add-result', function () {
//add check boxes
arrayUtils.forEach(legendLayers, function (layer) {
var layerName = layer.title;
var checkBox = new CheckBox({
name: "checkBox" + layer.layer.id,
value: layer.layer.id,
checked: layer.layer.visible
});
checkBox.on("change", function () {
var targetLayer = map.getLayer(this.value);
targetLayer.setVisibility(!targetLayer.visible);
this.checked = targetLayer.visible;
});
//add the check box and label to the toc
domConstruct.place(checkBox.domNode, dom.byId("toggle"), "after");
var checkLabel = domConstruct.create('label', {
'for': checkBox.name,
innerHTML: layerName
}, checkBox.domNode, "after");
domConstruct.place("<br />", checkLabel, "after");
});
});
//ADD THE LEGEND AND XY COORDINATES
map.on("layers-add-result", function (evt) {
// CYCLE through and grab all the layer names to add to the LEGEND PLUS
// Remove layers not inteneted for the legend.
var layerInfo = arrayUtils.map(evt.layers, function (layer, index) {
if (layer.layer.id === "PastLocations" || layer.layer.id === "District" || layer.layer.id === "weatherlayer") { return { }; } //Hides Layers in the Legend
else { return { layer: layer.layer, title: layer.layer.name }; } //Else return All others
});
// CYCLE through and grab all the layer names to add to the LEGEND
if (layerInfo.length > 0) {
var legendDijit = new Legend({
map: map,
layerInfos: layerInfo,
}, "legend");
legendDijit.startup();
legendDijit.refresh();
}
});
Solved! Go to Solution.
I know this is not the way to do this although I don know of any other way to accomplish what I am looking for...
This is how I put on a large band-aid
This gives you something like this in your panel... I have a container for Weather, Incidents, Other Layers.
If I do a little CSS work I can get ride of the frames and color backgrounds and make this look a little more appealing.
The example below does not have all the layers in the image. In my below example it would simply put one feature layer in each of the 3 accordions
Follow the "legendLayers1.push" below from each FeatureLayer to the function below it.
legendLayers1.push({ layer: WeatherImpactWashout, title: 'WeatherImpact Washout' });
legendLayers2.push({ layer: WeatherImpactWashout, title: 'WeatherImpact Washout' });
legendLayers2.push({ layer: WeatherImpactWashout, title: 'WeatherImpact Washout' });
<div id="IDAccordionPaneLayers" data-dojo-type="dijit.layout.AccordionContainer" style="color:black; height:90%; width:90%;">
<div id="idLayers2" data-dojo-type="dijit.layout.ContentPane" data-dojo-props="title:'Weather'" >
<div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="title:'Natural Disasters'">
<div id="toggle2" style="padding: 2px 2px; color:Black;"></div>
</div>
</div>
<div id="idLayers3" data-dojo-type="dijit.layout.ContentPane" data-dojo-props="title:'Incidents & Traffic'" >
<div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="title:'Natural Disasters'">
<div id="toggle3" style="padding: 2px 2px; color:Black;"></div>
</div>
</div>
<div id="idLayers1" data-dojo-type="dijit.layout.ContentPane" data-dojo-props="title:'Layers1'" >
<div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="title:'Natural Disasters'">
<div id="toggle1" style="padding: 2px 2px; color:Black;"></div>
</div>
</div>
</div>
var WeatherImpactPowerLines = new FeatureLayer("https://arcgis.vdem.virginia.gov/ArcGIS/rest/services/Traffic/VATraffic_WeatherImpactPoints/MapServe...", {
mode: FeatureLayer.MODE_ONDEMAND,
visible: false,
outFields:["*"],
infoTemplate: infoWeatherImpact
});
legendLayers1.push({ layer: WeatherImpactPowerLines, title: 'WeatherImpact Power Lines' });
var WeatherImpactOther = new FeatureLayer("https://arcgis.vdem.virginia.gov/ArcGIS/rest/services/Traffic/VATraffic_WeatherImpactPoints/MapServe...", {
mode: FeatureLayer.MODE_ONDEMAND,
visible: false,
outFields:["*"],
infoTemplate: infoWeatherImpact
});
legendLayers2.push({ layer: WeatherImpactOther, title: 'WeatherImpact Other' });
var WeatherImpactPassable = new FeatureLayer("https://arcgis.vdem.virginia.gov/ArcGIS/rest/services/Traffic/VATraffic_WeatherImpactPoints/MapServe...", {
mode: FeatureLayer.MODE_ONDEMAND,
visible: false,
outFields:["*"],
infoTemplate: infoWeatherImpact
});
legendLayers3.push({ layer: WeatherImpactPassable, title: 'WeatherImpact Passable' });
// ADD CHECK BOXES FOR LAYERS
map.on('layers-add-result', function () {
//add check boxes
arrayUtils.forEach(legendLayers1, function (layer) {
var layerName = layer.title;
var checkBox = new CheckBox({
name: "checkBox" + layer.layer.id,
value: layer.layer.id,
checked: layer.layer.visible
});
checkBox.on("change", function () {
var targetLayer = map.getLayer(this.value);
targetLayer.setVisibility(!targetLayer.visible);
this.checked = targetLayer.visible;
});
//add the check box and label to the toc
//domConstruct.place(checkBox.domNode, dom.byId("toggle"), "after");
domConstruct.place(checkBox.domNode, dom.byId("toggle1"), "after");
var checkLabel = domConstruct.create('label', {
'for': checkBox.name,
innerHTML: layerName
}, checkBox.domNode, "after");
domConstruct.place("<br />", checkLabel, "after");
});
arrayUtils.forEach(legendLayers2, function (layer) {
var layerName = layer.title;
var checkBox = new CheckBox({
name: "checkBox" + layer.layer.id,
value: layer.layer.id,
checked: layer.layer.visible
});
checkBox.on("change", function () {
var targetLayer = map.getLayer(this.value);
targetLayer.setVisibility(!targetLayer.visible);
this.checked = targetLayer.visible;
});
//add the check box and label to the toc
//domConstruct.place(checkBox.domNode, dom.byId("toggle"), "after");
domConstruct.place(checkBox.domNode, dom.byId("toggle1"), "after");
var checkLabel = domConstruct.create('label', {
'for': checkBox.name,
innerHTML: layerName
}, checkBox.domNode, "after");
domConstruct.place("<br />", checkLabel, "after");
});
arrayUtils.forEach(legendLayers3, function (layer) {
var layerName = layer.title;
var checkBox = new CheckBox({
name: "checkBox" + layer.layer.id,
value: layer.layer.id,
checked: layer.layer.visible
});
checkBox.on("change", function () {
var targetLayer = map.getLayer(this.value);
targetLayer.setVisibility(!targetLayer.visible);
this.checked = targetLayer.visible;
});
//add the check box and label to the toc
//domConstruct.place(checkBox.domNode, dom.byId("toggle"), "after");
domConstruct.place(checkBox.domNode, dom.byId("toggle1"), "after");
var checkLabel = domConstruct.create('label', {
'for': checkBox.name,
innerHTML: layerName
}, checkBox.domNode, "after");
domConstruct.place("<br />", checkLabel, "after");
});
});
//ADD THE LEGEND AND XY COORDINATES
map.on("layers-add-result", function (evt) {
// CYCLE through and grab all the layer names to add to the LEGEND PLUS
// Remove layers not inteneted for the legend.
var layerInfo = arrayUtils.map(evt.layers, function (layer, index) {
if (layer.layer.id === "PastLocations" || layer.layer.id === "District" || layer.layer.id === "weatherlayer") { return { }; } //Hides Layers in the Legend
else { return { layer: layer.layer, title: layer.layer.name }; } //Else return All others
});
// CYCLE through and grab all the layer names to add to the LEGEND
if (layerInfo.length > 0) {
var legendDijit = new Legend({
map: map,
layerInfos: layerInfo,
}, "legend");
legendDijit.startup();
legendDijit.refresh();
}
});
map.addLayers([
WeatherImpactPassable,WeatherImpactOther,WeatherImpactPowerLines
]);
I saw this example but its using a web map I have my layers all defined individually in my js page
But this is the functionality I am after....but I am not using a web map
Here is that sample using coded layers like you are wanting:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
<title>Layer List Dijit</title>
<link rel="stylesheet" href="http://js.arcgis.com/3.25/dijit/themes/claro/claro.css">
<link rel="stylesheet" href="http://js.arcgis.com/3.25/esri/css/esri.css">
<style>
html,
body,
.container,
#map {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
margin: 0;
font-family: "Open Sans";
}
#map {
padding: 0;
}
#layerListPane {
width: 25%;
}
.esriLayer {
background-color: #fff;
}
.esriLayerList .esriList {
border-top: none;
}
.esriLayerList .esriTitle {
background-color: #fff;
border-bottom: none;
}
.esriLayerList .esriList ul {
background-color: #fff;
}
</style>
<script>
var dojoConfig = {
parseOnLoad: true
};
</script>
<script src="http://js.arcgis.com/3.25/"></script>
<script>
require([
"esri/map",
"esri/layers/ArcGISDynamicMapServiceLayer",
"esri/dijit/LayerList",
"dojo/query",
"dojo/dom-construct",
"dojo/dom-class",
"dojo/dom-style",
"dojo/on",
"dojo/_base/array",
"dijit/layout/BorderContainer",
"dijit/layout/ContentPane",
"dojo/domReady!"
], function (
Map,
ArcGISDynamicMapServiceLayer,
LayerList,
query,
domConstruct,
domClass,
domStyle,
on,
array
) {
var map = new Map("map", {
basemap: "topo",
center: [-123, 47],
zoom: 8,
sliderStyle: "small"
});
var atlasLayer = new ArcGISDynamicMapServiceLayer("http://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer", {
"id": "atlasLayer",
"showAttribution": false
});
var recreationLayer = new ArcGISDynamicMapServiceLayer("http://sampleserver6.arcgisonline.com/arcgis/rest/services/Recreation/MapServer", {
"id": "recreationLayer",
"showAttribution": false
});
var waterNetLayer = new ArcGISDynamicMapServiceLayer("http://sampleserver6.arcgisonline.com/arcgis/rest/services/Water_Network/MapServer", {
"id": "waterNetworkLayer",
"showAttribution": false
})
map.addLayers([atlasLayer, recreationLayer, waterNetLayer]);
var llWidget = new LayerList({
map: map,
layers: [{
layer: atlasLayer,
id: "Atlas layers",
subLayers: true
},{
layer: recreationLayer,
id: "Recreation Layer",
subLayers: true
},{
layer: waterNetLayer,
id: "Water Network Layer",
subLayers: true
}],
showLegend: true,
showOpacitySlider: true
},"layerList");
llWidget.startup();
});
</script>
</head>
<body class="claro">
<div class="container" data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'headline',gutters:false">
<div id="layerListPane" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'right'">
<div id="layerList"></div>
</div>
<div id="map" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'"></div>
</div>
</body>
</html>
So from what I am seeing there are 3 map services each with an array of layers in them.
This reads through each service and creates the list allowing them to collapse?
Correct
Thinking.....I have infotemplates as well to control what I see. On a few of them I am doing more than simply reading from the Service for symbology etc.
Can I handle this with this code example?
// ADDRESS POINTS
var simpleJson = {
"type": "simple",
"label": "",
"description": "",
"symbol": {
"color": [255,255,51],
"size": 6,
"angle": 0,
"xoffset": 0,
"yoffset": 0,
"type": "esriSMS",
"style": "esriSMSCircle",
"outline": {
"color": [255,0,0],
"width": 1,
"type": "esriSLS",
"style": "esriSLSSolid"
}
}
}
var infoTemplateAddressPoints = new InfoTemplate();
infoTemplateAddressPoints.setTitle("Address Point Information");
infoTemplateAddressPoints.setContent("<table>" +
"<tr><td id='tblTitle'>Address Pts</td><td id='tblTitle2'></td></tr>" +
"<tr><td id='tblTitleLine'></td><td id='tblTitleLine2'></td></tr>" +
"<tr><td></td><td></td></tr>" +
"<tr><td id='tblMainline1'>Address</td><td id='tblSubline2'>${FULLADDR}</td></tr>" +
"<tr><td id='tblMainline1'>Municipality</td><td id='tblSubline2'>${MUNICIPALITY}</td></tr>" +
"<tr><td id='tblMainline1'>PO Name</td><td id='tblSubline2'>${PO_NAME}</td></tr>" +
"<tr><td id='tblMainline1'>Zip Code</td><td id='tblSubline2'>${ZIP_5}</td></tr>" +
"</table><hr>");
var AddressPointEndPoint = "https://xxxxxx/arcgis/rest/services/VA_Base_layers/VA_Address_Points/MapServer/0";
var AddressPoints = new FeatureLayer(AddressPointEndPoint, {
id: "AddressPoint",
minScale: 50000,
visible: true,
opacity: .7,
outFields: ["*"],
infoTemplate: infoTemplateAddressPoints
});
// Push layer to the legend
legendLayers.push({ layer: AddressPoints, title: 'Address Points' });
var rend = new SimpleRenderer(simpleJson);
AddressPoints.setRenderer(rend)
Jay,
Sure what I provided was just an example. All you really need of the code I provided is this portion:
var llWidget = new LayerList({
map: map,
layers: [{
layer: atlasLayer,
id: "Atlas layers",
subLayers: true
},{
layer: recreationLayer,
id: "Recreation Layer",
subLayers: true
},{
layer: waterNetLayer,
id: "Water Network Layer",
subLayers: true
}],
showLegend: true,
showOpacitySlider: true
},"layerList");
llWidget.startup();
You just change the layer property for your actual layer vars.
Say I wanted the Recreation in the atlasLayer Can I do this?
var llWidget = new LayerList({
map: map,
layers: [{
layer: atlasLayer,recreationLayer,
id: "Atlas layers",
subLayers: true
},
{
layer: recreationLayer,
id: "Recreation Layer",
subLayers: true
},{
layer: waterNetLayer,
id: "Water Network Layer",
subLayers: true
}],
showLegend: true,
showOpacitySlider: true
},"layerList");
llWidget.startup();
No. One layer per layer property.
So if I have 20 individual layers from multiple sources, with InfoTemplates.....
I want 3 categories...using your example...trying to figure out how I get like 10 in the first, 5 in the second and 5 in the third.... Each category will have layers from multiple sources....some external and some internal
Say I had this. How do I get both of these in onto the atlasLayer
// WMA LINE
var WMAFL = new FeatureLayer("https://xxxx/arcgis/rest/services/Projects/AVL/MapServer/4", {
mode: FeatureLayer.MODE_SNAPSHOT,
visible: true
});
// WMA FEATURES POINT
var WMAFPt = new FeatureLayer("https://xxxx/arcgis/rest/services/Projects/Locations/MapServer/2", {
mode: FeatureLayer.MODE_SNAPSHOT,
visible: true
});
var llWidget = new LayerList({
map: map,
layers: [{
layer: atlasLayer, // I WANT BOTH LAYERS IN THIS CATEGORY
id: "Atlas layers",
subLayers: true
},
{
layer: recreationLayer,
id: "Recreation Layer",
subLayers: true
},{
layer: waterNetLayer,
id: "Water Network Layer",
subLayers: true
}],
showLegend: true,
showOpacitySlider: true
},"layerList");
llWidget.startup();