I have the following code to grab a value from a drop down menu and use it to change the renderer of the featureLayer. However, it does not update the legend. The legend just stays on the initial, default renderer at page load.
I have tried adding a callback function after the switch
that would legend.refresh()
. That did indeed refresh the legend every time I changed the renderer, but oddly it was "one behind," always changing the legend to reflect the previous renderer instead of the current.
getRenderer = function(rendererFromSelect) {
renderer = rendererFromSelect.value;
switch(renderer) {
case "approval_rate":
map.removeLayer(featureLayer);
var generateRenderer = new GenerateRendererTask(featureLayerURL);
var params = new GenerateRendererParameters();
var classDef = new ClassBreaksDefinition();
classDef.breakCount = 5;
classDef.classificationField = "approval_rate";
classDef.classificationMethod = "quantile";
params.classificationDefinition = classDef;
generateRenderer.execute(params, applyRenderer);
function applyRenderer(renderer) {
featureLayer.setRenderer(renderer);
};
...other cases...
};
I have also tried this:
(1) Create a function to build the legend
(2) Call this function when the body loads
(3) Every time a new renderer is selected via drop down, legend.destroy()
(4) Then, after the renderer ids changed and the feature layer loads, create legend again.
So here is my function to create the legend. (I declare it as a global variable and define it inside the scope of the AMD so I call access it from the HTML.) This works great.
createLegend = function(titleStr){
legend = new Legend({
map: map,
layerInfos : [ {
layer : featureLayer,
title : titleStr
} ]
}, "legend");
legend.startup();
};
And here is where I change the renderer, load feature layer again, destroy legend and recreate after feature layer loads.
getRenderer = function(rendererFromSelect) {
renderer = rendererFromSelect.value;
switch(renderer) {
case "approval_rate":
map.removeLayer(featureLayer);
var generateRenderer = new GenerateRendererTask(featureLayerURL);
var params = new GenerateRendererParameters();
var classDef = new ClassBreaksDefinition();
classDef.breakCount = 5;
classDef.classificationField = "approval_rate";
classDef.classificationMethod = "quantile";
classDef.colorRamp = multiRamp;
params.classificationDefinition = classDef;
generateRenderer.execute(params, applyRenderer);
function applyRenderer(renderer) {
featureLayer.setRenderer(renderer);
};
legend.destroy()
map.addLayer(featureLayer);
map.removeLayer(highlightLayer);
map.addLayer(highlightLayer);
break;
....other cases...
}
featureLayer.on("update", createLegend(renderer));
}
When I try this approach, the legend is created successfully when the page loads initially. The legend.destroy() is also working properly. However, when createLegend is called again to rebuild the legend with the new renderer, I get init.js:148 Uncaught TypeError: Cannot read property 'firstChild' of null
So I'm wondering if legend.destroy()
destroys something that I need to create the legend again later?
EDIT: Indeed, legend.destroy()
was eliminating the destination div for my legend. So I now recreate that div before I build the legend. Now the legend refreshes almost correctly, but it is still refreshing based on the PREVIOUS renderer.
I tried calling createLegend
on "update-end"
instead of "update"
. That seemed to make no difference.