ramnathv / htmlwidgets

HTML Widgets for R
http://htmlwidgets.org
Other
790 stars 207 forks source link

repeated creation of objects in shiny #76

Closed smartinsightsfromdata closed 9 years ago

smartinsightsfromdata commented 9 years ago

My d3pie wrapper, rd3pie works fine. On the other hand, surprisingly during testing we found that in a reactive function in shiniy (e.g. a sliderInput) multiple pies were created!

We eliminated the issue with the following code:

  if (el.hasChildNodes()) {
//  alert(el.hasChildNodes());
    while (el.firstChild) {
      el.removeChild(el.firstChild);
    }
  }

See the entire code here.

A demo is available here. Take into account that the problem does not occur anymore because of the above fix.

Now I'm encountering a similar issue with datamaps.

Is this an expected behaviour?

Is there a better way to address the problem than the one above?

As I've already encountered this 2 times, perhaps it should be covered in one of the vignettes?

Thanks for these great packages!!

jcheng5 commented 9 years ago

The reason we don't automatically destroy the previous pie you rendered, is because ideally widgets will smoothly transition from one set of data to the next, like in this demo: https://jcheng.shinyapps.io/cranbubbles/

So yes, this is entirely expected behavior; if on each renderValue invocation you only add more elements but don't remove the previous ones, then this is the behavior you'll get.

In this case since you don't want to do that, you can call $(el).empty() to clear out the previous content. This is basically equivalent to your loop but shorter and likely faster.

This approach will also work for datamaps, but the very best thing for datamaps would be to detect when the new values are the same "shape" as the old values (say, the same regions with updated numbers), and update the existing map to the new values. This requires more advanced JavaScript skill and more intimate knowledge of the library you're wrapping.

smartinsightsfromdata commented 9 years ago

Thanks for the help. consider the issue closed as far as htmlwidgets goes. I'll try to study better ways to update the map, beside plain destruction!

mndrake commented 8 years ago

In case anyone else finds this thread looking for a hack solution (as I did). $(el).empty() will work in shiny since jquery is loaded, but not if running as an interactive session in the 'viewer' in RStudio. If you use d3.select(el).empty() then it will (should?) work in both places.

timelyportfolio commented 8 years ago

Without a library such as d3 or jquery, I have used el.innerHTML = "". Not sure what is fastest or best practice in the JavaScript world.

ramnathv commented 8 years ago

While using shiny, you already have access to jquery. So I would stick with $(el).empty() to avoid any browser incompatibilities. In other situations, I would do what @timelyportfolio recommended, but rarely do I write anything that does not include d3 :smile:

hafen commented 8 years ago

Along these lines, has there been any discussion about allowing widget developers to specify a destructor method for htmlwidgets? In most cases, it would be just removing the element from the dom but I have run into an issue with rthreejs, for example, where this is not sufficient (try removing the element and re-adding multiple times and eventually your browser will yell at you).