Early in my webR explorations, I started to wonder how we might pair htmlwidgets with webR.
Your first question is probably
Why would we want or need
htmlwidgetsin JavaScript if we are fully immersed in JavaScript?
Well, many htmlwidget authors carefully constructed their widget to allow an R user to stay
in their cozy R context with well documented arguments avoiding the unfamiliar land of JavaScript dealing with issues like data conversion. For instance react-table is a brilliant JavaScript library, but Greg Lin has done such an amazing job with reactable that even as an experienced JavaScript developer I prefer building with the R htmlwidget. So now that we have R in JavaScript (still hard for me to believe), we might want to benefit from the convenience of htmlwidgets.
Below is one approach to leveraging htmlwidgets in webR using the technique described in this post. We’ll follow these steps:
- Manually add dependencies with 
htmlwidgets::getDependency(). Eventually I will see if we can avoid this step and use thewebRvirtual file system to serve up the necessary files. - Initialize 
webR - Create our 
reactablehtmlwidget just like we would inR - Use the 
jsonoutside ofwebRin our top-level JavaScript to create thereactablein our web page 
It works, but I’m still left wondering whether anyone besides me would ever want to do this, and if so is there a better way.
loading…
Code
library(htmltools)
library(reactable)
tagList(
  # add dependencies for htmlwidget here,
  #   in this case for reactable we will need these
  reactR::html_dependency_react(),
  reactR::html_dependency_reacttools(),
  htmlwidgets::getDependency("reactable","reactable"),
  
  # load and init webr
  tags$script(HTML(
'
(async function() {
  const { WebR, ChannelType } = await import(
    "https://cdn.jsdelivr.net/npm/webr/dist/webr.mjs"
  );
  const webR = new WebR({
    channelType: ChannelType.PostMessage
  });
  await webR.init();
  await webR.installPackages(["reactable"]);
  // construct reactable and then get x component of the widget
  const rt_x = await webR.evalRString(`
    library(reactable)
    library(jsonlite)
    jsonlite::toJSON(reactable(mtcars, pagination=FALSE)$x, auto_unbox = TRUE, force = TRUE)
  `)
  console.log(rt_x);
  let rt_json = JSON.parse(rt_x);
  // also need to parse data in tag since it will be quoted
  rt_json.tag.attribs.data = JSON.parse(rt_json.tag.attribs.data);
  // use HTMLWidgets.widgets to give us
  // a list of available htmlwiget bindings
  //  in this case we should just have one
  // assume there might be lots, so filter for the one we want
  //  in this case, we want reactable
  const rt_binding = HTMLWidgets.widgets.filter(function(widget){
    return widget.name === "reactable"
  })[0];
  // get our htmlwidget DOM element
  const el = document.getElementById("myreactable");
  const instance = rt_binding.initialize(el);
  rt_binding.renderValue(
    el,
    rt_json,
    instance
  );
})()
'
  ))
)