See the following for more examples combining R/Shiny
and vuejs
. All keep a global state store (not good practice) updated by shiny::sendCustomMessage()
.
Please note this is for illustration purposes only. vue
is not needed at all, since all of this can easily be handled within Shiny
.
library(svglite)
library(shiny)
library(d3r)
ui <- tagList(
tags$div(
id = "app",
style = "height:400px; width:100%;",
tags$div(style = "width:49%;display:inline;float:left;",tag("svg", list())),
tags$div(style = "width:49%;display:inline;float:left;",tag("svg", list()))
),
tags$script(
"
var store = {svg: {scatter: '', density: ''}};
// add a very simple function that will update our store object
// with the svg data
Shiny.addCustomMessageHandler(
'updatePlot',
function(x) {
// mutate store data to equal the x argument
store.svg = x
}
);
// simple Vue app to monitor store and update plot when svg changes
var app;
$(document).on('shiny:connected', function(){
app = new Vue({
el: '#app',
data: store,
watch: {
svg: {
handler: function(newVal, oldVal) {
var svg_scatter = this.$el.querySelectorAll('svg')[0];
svg_scatter.outerHTML = newVal.scatter;
var svg_density = this.$el.querySelectorAll('svg')[1];
svg_density.outerHTML = newVal.density;
}
},
deep: true
}
})
});
"
),
vueR::html_dependency_vue()
)
server <- function(input, output, session) {
results <- NULL
observe({
invalidateLater(2000, session)
sim <- runif(10)
results <<- tail(c(results, sim),1000)
s_scatter <- svgstring(standalone = FALSE)
plot(seq_along(sim), sim)
dev.off()
s_density <- svgstring(standalone = FALSE)
plot(density(results))
dev.off()
session$sendCustomMessage(
type = "updatePlot",
message = list(
scatter = s_scatter(),
density = s_density()
)
)
})
}
shinyApp(ui, server)