简体   繁体   English

R闪亮的向javascript sendCustomMessage提供数据不起作用

[英]R shiny serve data to javascript sendCustomMessage not working

this is driving me crazy.这真让我抓狂。 I am using ag-grid directly as javascript package, as the wrapper rag-grid is outdated.我直接将 ag-grid 用作 javascript 包,因为包装器 rag-grid 已过时。

All the examples I looked at unfortunately are observing for a javascript event before sending a custom message, I don't need this as I just want to serve data at startup, but my code doesn't work, it returns:不幸的是,我看到的所有示例都是在发送自定义消息之前观察 javascript 事件,我不需要这个,因为我只想在启动时提供数据,但我的代码不起作用,它返回:

Error in func(fname, ...) : app.R did not return a shiny.appobj object.

what I want to achieve at the end will be我最终想要达到的目标是

  1. catch data from mysql with dbReadTable (DONE)使用 dbReadTable (DONE) 从 mysql 捕获数据
  2. serve data from R to javascript at startup在启动时将数据从 R 提供给 javascript
  3. render the initial values in the table呈现表中的初始值
  4. observe for edits in javascript and pass them to R观察javascript中的编辑并将它们传递给R
  5. process them in R to pass them to mysql with dbExecute在 R 中处理它们以使用 dbExecute 将它们传递给 mysql

however I am still stuck at point 2, trying to start the communication between backend and frontend.但是我仍然停留在第 2 点,试图开始后端和前端之间的通信。

This is the code.这是代码。

app.R应用程序.R

library(shiny)
library(RSQLite)
library(DBI)
library(tidyverse)

myjson <- '[
  {
    "ID": 1,
    "REQCAT": "cat 1"
  },
  {
    "ID": 2,
    "REQCAT": "cat 2"
  }
]'


#initialise database
con <- dbConnect(RSQLite::SQLite(), ":memory:")
#starting status of database
start <- as.data.frame(fromJSON(myjson))
dbWriteTable(con, "requests", start)
#testing reading
dbReadTable(con, "requests")
#testing writing
dbExecute(con,
    'INSERT INTO requests 
      (ID,REQCAT) 
        VALUES (3,"cat 3")
    ;')
dbReadTable(con, "requests")


###################
#### START APP ####
###################

ui <- fluidPage(
  #This tells shiny to include both css and scripts of aggrid
  tags$script(src="https://unpkg.com/ag-grid-enterprise/dist/ag-grid-enterprise.min.js"),
  titlePanel("Ag-Grid Basic Example"),
  uiOutput("myGrid_container")
)

server <- function(input, output, session) {
  data <- dbReadTable(con, "requests")
  dataJSON<-toJSON(data,pretty=TRUE,auto_unbox=TRUE)
  session$sendCustomMessage("jsondata",dataJSON)
  #This tells shiny to run our javascript file "script.js" and send it to the UI for rendering
  output$myGrid_container<- renderUI({
    tagList(
      div(id = "myGrid", style="height: 200px; width:500px;", class="ag-theme-alpine"),
      tags$script(src="script.js")
    )
  })
}

shinyApp(ui = ui, server = server)

dbDisconnect(con)

script.js in www subfolder www 子文件夹中的 script.js

const gridOptions = {
  columnDefs: [
    { field: "ID" },
    { field: "REQCAT" }
  ],
  defaultColDef: {
    flex: 1,
    editable: true,
  },
  rowData: getRows(),
  enableRangeSelection: true,
  enableFillHandle: true,
  undoRedoCellEditing: true,
  undoRedoCellEditingLimit: 5,
  enableCellChangeFlash: true,
  onFirstDataRendered: onFirstDataRendered,
  onCellValueChanged: onCellValueChanged,
};

function undo() {
  gridOptions.api.undoCellEditing();
}

function redo() {
  gridOptions.api.redoCellEditing();
}

function onFirstDataRendered() {
  setValue('#undoInput', 0);
  disable('#undoInput', true);
  disable('#undoBtn', true);

  setValue('#redoInput', 0);
  disable('#redoInput', true);
  disable('#redoBtn', true);
}

function onCellValueChanged(params) {
  var undoSize = params.api.getCurrentUndoSize();
  setValue('#undoInput', undoSize);
  disable('#undoBtn', undoSize < 1);

  var redoSize = params.api.getCurrentRedoSize();
  setValue('#redoInput', redoSize);
  disable('#redoBtn', redoSize < 1);
}

function disable(id, disabled) {
  document.querySelector(id).disabled = disabled;
}

function setValue(id, value) {
  document.querySelector(id).value = value;
}

function getRows() {
  Shiny.addCustomMessageHandler("jsondata", myfunction );
// this function is called by the handler, which passes the message
  function myfunction(message){
      const rowData = message;
      return rowData;
  }
}

// setup the grid after the page has finished loading
const gridDiv = document.querySelector('#myGrid');
new agGrid.Grid(gridDiv, gridOptions);

I also tried the option of having includeScript("www/script.js"), in the UI but I had no luck.我还尝试了在 UI 中使用 includeScript("www/script.js") 的选项,但我没有运气。

Any hint on how to proceed?关于如何进行的任何提示?

Thanks谢谢

$(document).ready(function () {

    // all your "helper" functions here

    function gridOptions(rowData) {
        return {
            columnDefs: [
                { field: "ID" },
                { field: "REQCAT" }
            ],
            defaultColDef: {
                flex: 1,
                editable: true,
            },
            rowData: rowData,
            enableRangeSelection: true,
            enableFillHandle: true,
            undoRedoCellEditing: true,
            undoRedoCellEditingLimit: 5,
            enableCellChangeFlash: true,
            onFirstDataRendered: onFirstDataRendered,
            onCellValueChanged: onCellValueChanged,
        };
    }

    const gridDiv = document.querySelector('#myGrid');

    Shiny.addCustomMessageHandler("jsondata", function (rowData) {
        new agGrid.Grid(gridDiv, gridOptions(rowData));
    });

});

and in the Shiny app, remove the renderUI and:在 Shiny 应用程序中,移除renderUI并:

ui <- fluidPage(
  tags$head(
    tags$script(src = "https://unpkg.com/ag-grid-enterprise/dist/ag-grid-enterprise.min.js"),
    tags$script(src = "myscript.js")
  ),
  titlePanel("Ag-Grid Basic Example"),
  div(id = "myGrid", style = "height: 200px; width:500px;", class = "ag-theme-alpine")
)

I'm not familiar with this JavaScript library, but it would be strange that rowData has to be a JSON string, and you are giving a JSON string with this code, because you use toJSON .我不熟悉这个 JavaScript 库,但奇怪的是rowData必须是 JSON 字符串,并且您使用此代码提供 JSON 字符串,因为您使用toJSON So either remove toJSON in the R code (Shiny automatically takes care of the conversion), or use JSON.parse in the JavaScript code.因此,要么在 R 代码中删除toJSON (Shiny 自动处理转换),要么在 JavaScript 代码中使用JSON.parse The toJSON method can be useful if the data passed to JavaScript has not the required format (you can control the format of a jsonified dataframe with toJSON ).如果传递给 JavaScript 的数据没有所需的格式(您可以使用toJSON控制 jsonified 数据帧的格式),则toJSON方法会很有用。 I would first try without toJSON and use console.log to check the format.我会首先尝试不使用toJSON并使用console.log检查格式。 If the format is not the required one, I would switch to the toJSON method.如果格式不是必需的,我会切换到toJSON方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM