I'm trying to develop a robust way to generate a UI incorporating map layer controls such as a base layer selector. I've read several posts including this recent one but I'm still not able to change the visibility of the layers and always seem to return an error 'layer.setVisible is not a function'. Once I have a reliable method, I will be developing other controls for layer-styling etc.

I've followed several tutorials and generated a layer tree with opacity controls for example, but even though all of my layers are in groups, the layer tree generates several 'undefined' layers which I can't locate. Hence the reason I would like to build this from scratch, so that I can understand how to include or exclude layers and ensure that the ui is bound to the map object.

I'm aware of Matt Walker's LayerSwitcher but again, it doesn't really do what I want and I'm struggling to understand the 'layer walking' process adequately. Below is a sample of my code:

function getBaseGroup() {
var layers = map.getLayers();
var len = layers.getLength(), l;
for (var i = 0; i < len; i++) {
    l = layers.item(i);
    var lt = l.get('title');
    // check for layers within groups
    if (lt == 'Base Layers') { // Title of Group
        if (l.getLayers) {
            var innerLayers = l.getLayers().getArray();
            var base = [];
            for (var j = 0; j < innerLayers.length; j++) {
            return base;

function showBase() {
var this_ = this;
var sel = $('#baseMapLayer');
var layers = getBaseGroup();

layers.forEach(function (layer) {
    sel.append($("<option>").attr('value', layer.title).text(layer.title));

$(sel).change(function () {
    var selectedValue = $(this).find(":selected").val();
    console.log("the value you selected: " + selectedValue);
    layers.forEach(function (layer) {
        console.log(layer); // returns layer object
        if (layer.title == selectedValue) {
            console.log(layer.title); // returns title
        else {
  • Updated forEach loop still returning layer.setVisible is not a function: layers.forEach(function (layer) { console.log(layer.title); if (layer.title == selectedValue) { console.log(layer.title); layer.setVisible(true); } else { layer.setVisible(false); } }); – dvmac01 Oct 22 '15 at 15:18

Its hard to find out what is wrong as long as we dont have your whole work. map.getLayers() gives back all the layers exist on map and these may be layers generated internally by ol3 for interactions etc. I would put layers, I am intersted in, into an array or an ol.collection and I would use this object then. You can always set an extra attribute when initialising your layers object. For example:

var baseLayer = new ol.layer.Tile({
        visible: false,
        preload: Infinity,
        source: new ol.source.BingMaps({
            key: 'Ak-dzM4wZjSqTlzveKz5u0d4IQ4bRzVI309GxmkgSVr1ewS6iPSrOvOKhA-CJlm3',
            imagerySet: 'AerialWithLabels'

and then you may filter layers exist in your switcher only. like so:

var allLayrs = map.getLayers();
layers.forEach(function (layer) {
    if (layer.get('DISPLAY_IN_SWITCHER')===true){
    console.log("this layer is listed in my tree",layer);

  • Thanks Pavlos, I currently have a property type: 'base' and these are part of a layer group. My getBaseGroup function successfully gets these but I'm not sure why the (sel).change part of my showBase function isn't working. I've tried layer.setVisible and layer.set('visible', true). Can you help me to understand why code if (layer.get('title') === "selectedValue")code returns layer.get is not a function? – dvmac01 Oct 22 '15 at 14:12
  • this means that layer passed is not a proper ol.layer. If attribute "title" was missing should return undifined. try to log your layer in the console to see what is it. layers.forEach(function (layer) {consol.log("layer obj:",layer);}); – pavlos Oct 22 '15 at 14:20
  • But that's the thing - I deleted it for brevity but the first line of my forEach logged a proper layer object, complete with title. I've added a comment just below my question as I've refined the function a little but I still get the same 'layer.setVisible is not a function'. – dvmac01 Oct 22 '15 at 15:18
  • I've updated my code Pavlos to reflect the new forEach function. – dvmac01 Oct 22 '15 at 15:35
  • so you are sure you get a proper layer object (ol.layer} but still get layer.setVisible is not a function. Do you use firebug???? If so try to view the layer object and check whether is a proper layer. Unless you make a fiddle I can only guess what the problem is. – pavlos Oct 22 '15 at 16:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.