ramnathv / htmlwidgets

HTML Widgets for R
http://htmlwidgets.org
Other
792 stars 206 forks source link

Print methods for widgets and rendering in R Markdown #59

Closed hafen closed 9 years ago

hafen commented 9 years ago

I have a widget where I build and update an object through various commands and then it is not until the object is printed that createWidget() is called. I have good reasons for this and it will probably be a common use case. This results in behavior where if I am in an interactive console and I print my object, the widget is rendered in the browser, but if I embed the same code in an R Markdown document, the widget is not embedded in the resulting document.

As an example, take the widget you get from scaffoldWidget() but modify mywidget.R to have the following:

mywidget <- function(message, width = NULL, height = NULL) {
  structure(list(message = message, width = width, height = height), 
    class = "mywidgetobj")
}

print.mywidgetobj <- function(x, ...) {
  w <- htmlwidgets::createWidget(
    name = 'mywidget',
    list(message = x$message),
    width = x$width,
    height = x$height,
    package = 'mywidget'
  )
  print(w)
}

Now the following will give me back the widget when run in an interactive console:

a <- mywidget("hello world")
a

But in an R Markdown document, it also opens the widget in the browser when it should instead be embedding it in the document.

ramnathv commented 9 years ago

Can you elaborate more on why you want to postpone calling createWidget? I would like to understand the use case better before heading down this path.

jjallaire commented 9 years ago

One of the reasons for this is that a different S3 method is used for the knitr case. In that case it's actually the knit_print method rather than the print method so you probably just need to explicitly implement knit_print. See:

https://github.com/ramnathv/htmlwidgets/blob/master/R/knitr-methods.R#L36-L38

On Mon, Dec 29, 2014 at 6:55 PM, Ramnath Vaidyanathan < notifications@github.com> wrote:

Can you elaborate more on why you want to postpone calling createWidget? I would like to understand the use case better before heading down this path.

— Reply to this email directly or view it on GitHub https://github.com/ramnathv/htmlwidgets/issues/59#issuecomment-68316845.

hafen commented 9 years ago

@ramnathv, the idea for postponing is that in this case the object to be passed to createWidget will be built incrementally and the most natural way to view the widget is through printing the final object (think of building a plot object through a series of commands and then simply typing the name of the plot object to show it). Regardless of that, I suppose the real issue is reliably displaying widgets through a print method.

@jjallaire, your suggestion worked - thanks - I had gone down that route but missed the registerMethods stuff that was required to make it work. I'll close.

jjallaire commented 9 years ago

Okay, glad that worked!

Curious about the widget you are working on -- can you share any details about it at this point?

ramnathv commented 9 years ago

@hafen, I think I understand your use case. Note that it is possible to construct the plot using createWidget and then manipulate it downstream as you would manipulate any R object. My implementation of rCharts for htmlwidgets uses this design pattern and is consistent with how ggvis does it.