Black Lives Matter. Please consider donating to Black Girls Code today.
Learn how to use COVID-19 data in open source Dash apps. Register for the Sept 23rd webinar with IQT!

Update view after every iteration: plotly.js addTraces loop

I think all you need to get the desired behaviour is to wrap your Plotly.addTraces calls in a setTimeout.

See example: http://codepen.io/etpinard/pen/KrvyLk

1 Like

look like that is what I need, thank you. however when wrapping plotly.addTraces in a timeout I get an error:

Can you share a code snippet?

Sure thank you

original call happens within a timeout:

    setTimeout(function(){ 
              $scope.createLayoutObject();
              $scope.createGraphObject();
              $scope.drawGraphToView();         
    }, 0);

once layout and graphObject are created we have:

graphObject as $scope.graphPlots2:


and layout as $scope.layout2:
“sorry new user: only one image” --> the image is in the stackoverflow link

$scope.drawGraphToView() function goes here:

$scope.drawGraphToView = function(regroup){
    //true if first response/download chunk from server or regroup(not downloading but redefining grouping of traces so all downlod chunks in grapPlotsChunk/graphPlots2)
    if(query.page < 2 || regroup){
         if(regroup){
            for(c=0; c < $scope.graphPlotsChunk.length; c++ ){
              if(c == 0){
                Plotly.newPlot(graphRender, [$scope.graphPlots2[c]], $scope.layout2);
              }else{   
                Plotly.addTraces(graphRender, $scope.graphPlots2[c]);
              }
            }
         }else{
          Plotly.newPlot(graphRender, $scope.graphPlots2, $scope.layout2);
         }
    }else{
      for(k=0; k < $scope.graphPlotsChunk.length; k++ ){
              var traceName= _.find(graphRender.data, function (obj,index) {
                if(obj.name == $scope.graphPlotsChunk[k].name){
                  $scope.traceIndex = index;
                  return obj.name == $scope.graphPlotsChunk[k].name;
                }
              });
              if(traceName == undefined){
                  Plotly.addTraces(graphRender, $scope.graphPlots2[k]);
              }else{
                var update = {
                  x:[$scope.graphPlotsChunk[k].x],
                  y:[$scope.graphPlotsChunk[k].y]
                };
                Plotly.extendTraces(graphRender, update, [$scope.traceIndex]);
              }
      }
    }  
};

Something is up with the second arguments you’re passing to Plotly.addTraces.

The error you’re seeing is thrown when that second argument is undefined. See source code.

sorry the error is only if i wrap the add traces function in an extra timeout. The code you are looking at runs without error. Erros shows if I do:

     if(regroup){
        for(c=0; c < $scope.graphPlotsChunk.length; c++ ){
          if(c == 0){
            Plotly.newPlot(graphRender, [$scope.graphPlots2[c]], $scope.layout2);
          }else{   
            setTimeout( function(){
                 Plotly.addTraces(graphRender, $scope.graphPlots2[c]);
            },0);
          }
        }
     }else{
      Plotly.newPlot(graphRender, $scope.graphPlots2, $scope.layout2);
     }

looks like a race condition?

check:

     $scope.testCounter=[];
     if(regroup){
      ...   
        for(c=0; c < $scope.graphPlotsChunk.length; c++ ){
          setTimeout(function() { 
            $scope.testCounter.push(_.clone(c));
            console.log($scope.testCounter);
            Plotly.addTraces(graphRender, $scope.graphPlots2[c]);
          },0);    
        ...

using foreach instead of for allowed me to us setTimeout without issues, now all good, not sure why:

    $scope.graphPlots2.forEach(function(trace, i) {
       if(i==0){
         Plotly.newPlot('graphRender', [trace], $scope.layout2);
       }else{
          setTimeout(function() {
            Plotly.addTraces('graphRender', trace);
          }, 0);
       }
    });