javascriptjqueryrshinyv8

Using Javascript package in R


I'm trying to make an R shiny app where I can add GridStack widgets into a grid using Javascript, and I am following this post right here.

library(shinydashboard)
library(shiny)
library(shinyjs)
library(shinyjqui)
library(gridstackeR)


ui <- fluidPage (
  useShinyjs(),
  includeCSS("www/app.css"),
  tags$head(
    tags$script(src = "https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.0.1/gridstack.min.js"),
    tags$script('
    function addFirstWidget() {
      var el = $.parseHTML("<div class=\"grid-stack-item-content\">First Widget Content</div>");
      var grids = $(".grid-stack").data("gridstack");
      grids.add_widget(el, 1, 1, 4, 1, true);
    }
')
  ),
  grid_stack(
    grid_stack_item()
  ),
  actionButton("first_widget", "First Widget"),
  
  title = "Gridstack Prototype"
)

server <- function(input, output, session) {
  observeEvent(input$first_widget, {
    # browser()
    runjs("addFirstWidget();")
  })

}

shinyApp(ui = ui, server = server)

I know that '$(".grid-stack")" selects the grid-stack class for sure, since I tried the code with

function addFirstWidget() {
      $(".grid-stack").css("background-color", "red")
    }

and it turns the grid-stack class red, as expected.

Do I need to install the GridStack.js package with the V8 package on R or something? I've tried that with this:

engine <- v8()
uri <- paste0("https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.0.1/gridstack.min.js")
engine$source(uri)

But this just gives me an error saying: "Error in context_eval(join(src), private$context, serialize, await) : SyntaxError: Unexpected token {"

I've seen the ideas for browserifying JS packages but I have no idea how to do that for this because the first step requires me to source the uri, but the uri doesn't give me anything that works.


Solution

  • You don't need to involved v8 at all here. You want everything to run in the browser. Part of the problem is that the code you point to is from 2017 and I think the package has changed a lot since then. If I check more up-to-date documentation things look different. Here are some changes you will need to make. First, import the version that has all the code and make sure to specify type="'module'" since the code uses import statements.

    tags$script(src = "https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.0.1/gridstack-all.min.js", type='module'),
    

    I would give your gid_stack an ID to make it easier to find programatically.

    grid_stack(id="mygrid"),
    

    Then for the script, use something like

    tags$script(HTML('
    function addFirstWidget() {
      var grid = helper_find_grid_by_id("mygrid")
      grid.addWidget(
        "<div class=\'grid-stack-item-content\'>First Widget Content</div>", 
        {x: 1, y: 1, w: 4, h:1}
      );
    }
    '))
    

    Note the use of HTML() to make sure your function doesn't get escaped. And I wasn't sure what the values of 1, 1, 4, 1 were supposed to represent so I just guessed. You may need to adjust that after reading the docs.