0

I have a button on my map where when user clicks, it will filter 1 cartodb layer with SQL. I want to allow each button click to filter two layers, each sharing the same field and value. Here is the working map

<link rel="stylesheet" href="http://libs.cartocdn.com/cartodb.js/v3/3.11/themes/css/cartodb.css" />
</head>
<body>
<div id="map"></div>
    <nav>
<div id="layer_selector" class="menu-item">
<h4><a href="#">Supervisor Districts</a></h4>
<ul>
<li data="all" class="selected">All Districts</li>
<li data="1">District 1</li>
<li data="2">District 2</li>
<li data="3">District 3</li>
<li data="4">District 4</li>
<li data="5">District 5</li>
</ul>
</div>
    </nav>
<!-- include cartodb.js library -->
<script src="http://libs.cartocdn.com/cartodb.js/v3/3.11/cartodb.js"></script>
<script>
// create layer selector
function createSelector(layer) {
var sql = new cartodb.SQL({ user: 'pledgemap' });
var $options = $('#layer_selector li');
$options.click(function(e) {
// get the area of the selected layer
var $li = $(e.target);
var area = $li.attr('data');
// deselect all and select the clicked one
$options.removeClass('selected');
$li.addClass('selected');
// create query based on data from the layer
var query = "select * from sup_dist_2011";
if(area !== 'all') {
query = "select * from sup_dist_2011 where sup_dist_n  = " + area;  
}

// change the query in the layer to update the map
layer.setQuery(query);
});
} 

function main() {
cartodb.createVis('map', 'http://pledgemap.cartodb.com/api/v2/viz/c812bb36-b71d-11e4-b921-0e4fddd5de28/viz.json', {
tiles_loader: true,
center_lat: 34.15,
center_lon: -118,
zoom: 10
})

.done(function(vis, layers) {
// layer 0 is the base layer, layer 1 is cartodb layer
createSelector(layers[1])
})
.error(function(err) {
console.log(err);
});
}
window.onload = main;
</script>


</html> 
1

If you have multiple layers and you're pulling the data using a viz.json file, then the structure of the layer callback object is: layer[0] is the basemap, layer[1] are the static layers. There are one to many sublayers in layers[1]. If you are using createLayer, then the layer object consists of the multiple sublayers.

If you're pulling the data from a viz.json file, your situation is probably like this:

cartodb.createVis('map','vizjson_link')
    .done(function(vis,layers) {
    var sublayer0 = layers[1].getSubLayer(0);
    var sublayer1 = layers[1].getSubLayer(1);

    $("#change-sublayer0").on('click',function(e) {
        sublayer0.setSQL(sql_string0);
    });

    $("#change-sublayer1").on('click',function(e) {
        sublayer1.setSQL(sql_string1);
    });

});

We also tried to address this in a Map Academy lesson on CartoDB.js: http://academy.cartodb.com/courses/03-cartodbjs-ground-up/lesson-3.html

Edit: There are three sublayers in layers[1]. Therefore, when you call createSelector(layers[1]), you can extract these sublayers like above within createSelector:

var sublayerSup = layer.getSubLayer(0);
var sublayerPledge = layer.getSubLayer(1);

You can then change the query applied to each of these in the if statement you set up:

var querySup = "SELECT * FROM sup_dist_2011";
var queryPledge = "SELECT * FROM pledge";

if(area !== 'all') {
  querySup = querySup + " where sup_dist_n  = " + area;
  queryPledge = queryPledge + " WHERE pledge = " + otherAttribute;
}

// change the query in the layer to update the map
sublayerSup.setSQL(querySup);
sublayerPledge.setSQL(queryPledge);

You should probably also add another data attribute to your list elements so that you can pull additional information from them:

<li data="all" class="selected">All Districts</li>
<li data="1" data-pledge="blah1">District 1</li>
<li data="2" data-pledge="blah2">District 2</li>
<li data="3" data-pledge="blah3">District 3</li>
<li data="4" data-pledge="blah4">District 4</li>
<li data="5" data-pledge="blah5">District 5</li>

Again within createSelector you can extract this data like this:

var pledge = $li.data('pledge');

By the way, you don't need to use the var sql = new cartodb.SQL(...) line because you're only interacting with sublayers, not the SQL component of CartoDB.js.

A little ramble-y, but hope it helps!

| improve this answer | |
  • thank you for that. I updated my question and code. I am very novice at javascript and cartodb. Not sure where in the code to allow sublayer queries. – mapmedia Feb 20 '15 at 16:53
  • ok, updated answer to reflect new info. – Andy Eschbacher Feb 21 '15 at 19:43

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.