Accepted answer

This is a good example where a LOT of d3's enter/update/exit selection can be implemented.

Yeah, I agree: recreating a chart on every change isn't a good solution.

Okay, so here's a fork of your Plunkr using enter/update/merge/exit methods.

A preview of how I got the merge selection done: Let's take rowLabels for example:

// make region labels
var rowLabels = rowLabelGroup

// After merging the entered elements with the update selection,
// apply operations to both.

    .enter().append('text').attr('class', 'rowLabel mono')
    .attr('font-weight', 'normal')
    .style('text-anchor', 'end')
    .on('mouseover', function(d) {'font-weight', 'bold').style('fill', 'red');
    .on('mouseout', function(d) {'font-weight', 'normal').style('fill', 'black');
    .attr('x', 0)
    .attr('y', function(d, i) {
        return i * cellSize;
    .attr('transform', function(d, i) {
        return 'translate(-3, 11)';
    .attr('name', function(d) {
        return d;
    .text(function(d) {
        return d;
    .attr('id', function(d) {
        return 'rowLabel_' + yLabelsNames.indexOf(d);           
    .attr('label-r', function(d) {
        return yLabelsNames.indexOf(d);

// exit/remove elements which are no longer in use

Similarly, these methods have been applied to colLabels, cells and sparkLineSvgs as you can notice in the code.

And regarding appending of the SVGs, I've moved that code to outside the updateHeatmap function. And yes, btw, I've changed the name of the function from createHeatmap to updateHeatmap.

And I did encounter an issue while hovering over for the tooltip i.e. the tooltip flickered a lot. To counter that, I've added pointer-events:none to .d3-tip tooltip.

Go through the code and let me know if I've missed on anything or if you face issue understanding any part.

Hope it helps.

Related Query

More Query from same tag