【问题标题】:Rendering Katex in multiple tables in an R Shiny App在 R Shiny 应用程序的多个表中渲染 Katex
【发布时间】:2021-07-29 21:00:55
【问题描述】:

我正在使用来自以下帖子的 Stéphane Laurent 的“EDIT 2”解决方案

Math mode in shiny table

在 R Shiny 表中渲染数学。但是,当应用程序中存在多个表时,只会呈现第一个表(请参见下面的表示)。

我无法在多个表中使用此功能,因此我们将不胜感激!

library(shiny)

js <- " 
$(document).on('shiny:value', function(event) {
  if(event.name === 'table'){
    var matches = event.value.match(/(%%+[^%]+%%)/g);
    var newvalue = event.value;
    for(var i=0; i<matches.length; i++){
      var code = '\\\\' + matches[i].slice(2,-2);
      newvalue = newvalue.replace(matches[i], katex.renderToString(code));
    }
    event.value = newvalue;
  }
})
" 

ui <- fluidPage(
  tags$head(
    tags$link(rel="stylesheet", href="https://cdn.jsdelivr.net/npm/katex@0.10.0-beta/dist/katex.min.css", integrity="sha384-9tPv11A+glH/on/wEu99NVwDPwkMQESOocs/ZGXPoIiLE8MU/qkqUcZ3zzL+6DuH", crossorigin="anonymous"),
    tags$script(src="https://cdn.jsdelivr.net/npm/katex@0.10.0-beta/dist/katex.min.js", integrity="sha384-U8Vrjwb8fuHMt6ewaCy8uqeUXv4oitYACKdB0VziCerzt011iQ/0TqlSlv8MReCm", crossorigin="anonymous"),
    tags$script(HTML(js))
  ),
  titlePanel("Hello Shiny!"),
  mainPanel(
    numericInput("mean", "Enter mean", value = 1),
    numericInput("mean_2", "Enter 2nd mean", value = 2),
    tableOutput("table"),
    tableOutput("table_2")
  )
)

server <- function(input, output) {
  
  output$table <- renderTable({
    x <- rnorm(2)
    y <- rnorm(2, input$mean)
    tab <- data.frame(x = x, y = y, z = c("hello", "%%gamma%%%%delta%%"))
    rownames(tab) <- c("%%alpha%%", "%%beta%%")
    tab
  }, rownames = TRUE)
  
  output$table_2 <- renderTable({
    x <- rnorm(2)
    y <- rnorm(2, input$mean_2)
    tab <- data.frame(x = x, y = y, z = c("hello", "%%eta%%%%epsilon%%"))
    rownames(tab) <- c("%%alpha%%", "%%beta%%")
    tab
  }, rownames = TRUE)
  
}

shinyApp(ui, server)

编辑:

第二个问题是当表格事件被封装在 ns() 中时,如何在模块中实现这一点。请在下面找到演示此问题的代表:

app.R

library(shiny)
library(shinydashboard)

source("table1.R")
source("table2.R")

ui = dashboardPage(

header = dashboardHeader(),

body = dashboardBody(
  
  tabItems(
    
    tabItem(tabName = "table_1",
            table1UI(id = "table1id")),
    
    tabItem(tabName = "table_2",
            table2UI(id = "table2id"))
    
    ) # Closes tabItems

), # Closes dashboard body

sidebar = dashboardSidebar(
  
  width = 272.25, # Header is 230px button is 42.5px
  
  minified = FALSE,
  
  sidebarMenu(
    menuItem("Table 1", tabName = "table_1", icon = icon("chalkboard-teacher"))),
    menuItem("Table 2", tabName = "table_2", icon = icon("chalkboard-teacher")))

) # Closes UI

server = function(input, output, session) { 

callModule(module = table1,
           id = "table1id")

callModule(module = table2,
           id = "table2id")


} # Closes Server

  shinyApp(ui, server)

table1.R

js <- "
$(document).on('shiny:value', function(event) {
  if(event.name === 'table_1'){
    var matches = event.value.match(/(%%+[^%]+%%)/g);
    var newvalue = event.value;
    for(var i=0; i<matches.length; i++){
      var code = '\\\\' + matches[i].slice(2,-2);
      newvalue = newvalue.replace(matches[i], katex.renderToString(code));
    }
    event.value = newvalue;
  }
})
"

table1UI <- function(id) {
  
  ns <- NS(id)

  fluidRow(
    
    tags$head(
      tags$link(rel="stylesheet", href="https://cdn.jsdelivr.net/npm/katex@0.10.0-beta/dist/katex.min.css", integrity="sha384-9tPv11A+glH/on/wEu99NVwDPwkMQESOocs/ZGXPoIiLE8MU/qkqUcZ3zzL+6DuH", crossorigin="anonymous"),
      tags$script(src="https://cdn.jsdelivr.net/npm/katex@0.10.0-beta/dist/katex.min.js", integrity="sha384-U8Vrjwb8fuHMt6ewaCy8uqeUXv4oitYACKdB0VziCerzt011iQ/0TqlSlv8MReCm", crossorigin="anonymous"),
      tags$script(HTML(js))
    ),
    
    tagList(
    numericInput(ns("mean"), "Enter mean", value = 2),
    tableOutput(outputId = ns("table_1"))
    ))
} # Closes UI

table1 <- function(input, output, session, mean) {
  
  output$table_1 <- renderTable({
    x <- rnorm(2)
    y <- rnorm(2, input$mean)
    tab <- data.frame(x = x, y = y, z = c("hello", "%%gamma%%%%delta%%"))
    rownames(tab) <- c("%%alpha%%", "%%beta%%")
    tab
  }, rownames = TRUE)
  
} # Closes server

table2.R

js <- "
$(document).on('shiny:value', function(event) {
  if(event.name === 'table_2'){
    var matches = event.value.match(/(%%+[^%]+%%)/g);
    var newvalue = event.value;
    for(var i=0; i<matches.length; i++){
      var code = '\\\\' + matches[i].slice(2,-2);
      newvalue = newvalue.replace(matches[i], katex.renderToString(code));
    }
    event.value = newvalue;
  }
})
"

table2UI <- function(id) {
  
  ns <- NS(id)

  fluidRow(
    
    tags$head(
      tags$link(rel="stylesheet", href="https://cdn.jsdelivr.net/npm/katex@0.10.0-beta/dist/katex.min.css", integrity="sha384-9tPv11A+glH/on/wEu99NVwDPwkMQESOocs/ZGXPoIiLE8MU/qkqUcZ3zzL+6DuH", crossorigin="anonymous"),
      tags$script(src="https://cdn.jsdelivr.net/npm/katex@0.10.0-beta/dist/katex.min.js", integrity="sha384-U8Vrjwb8fuHMt6ewaCy8uqeUXv4oitYACKdB0VziCerzt011iQ/0TqlSlv8MReCm", crossorigin="anonymous"),
      tags$script(HTML(js))
    ),
    
    tagList(
    numericInput(ns("mean_2"), "Enter 2nd mean", value = 2),
    tableOutput(outputId = ns("table_2"))
    ))
} # Closes UI

table2 <- function(input, output, session, mean_2) {
  
  output$table_2 <- renderTable({
    x <- rnorm(2)
    y <- rnorm(2, input$mean_2)
    tab <- data.frame(x = x, y = y, z = c("hello", "%%eta%%%%epsilon%%"))
    rownames(tab) <- c("%%alpha%%", "%%beta%%")
    tab
  }, rownames = TRUE)
  
} # Closes server

【问题讨论】:

    标签: r shiny katex


    【解决方案1】:

    尝试替换

    if(event.name === 'table')
    

    if(event.name === 'table' || event.name === 'table_2')
    

    使用模块的应用:

    library(shiny)
    library(shinydashboard)
    
    table1UI <- function(id) {
      
      ns <- NS(id)
      
      fluidRow(
        tagList(
          numericInput(ns("mean"), "Enter mean", value = 2),
          tableOutput(outputId = ns("table_1"))
        )
      )
      
    } # Closes UI
    
    table1 <- function(input, output, session, mean) {
      
      output$table_1 <- renderTable({
        x <- rnorm(2)
        y <- rnorm(2, input$mean)
        tab <- data.frame(x = x, y = y, z = c("hello", "%%gamma%%%%delta%%"))
        rownames(tab) <- c("%%alpha%%", "%%beta%%")
        tab
      }, rownames = TRUE)
      
    } # Closes server
    
    table2UI <- function(id) {
      
      ns <- NS(id)
      
      fluidRow(
        tagList(
          numericInput(ns("mean_2"), "Enter 2nd mean", value = 2),
          tableOutput(outputId = ns("table_2"))
        )
      )
      
    } # Closes UI
    
    table2 <- function(input, output, session, mean_2) {
      
      output$table_2 <- renderTable({
        x <- rnorm(2)
        y <- rnorm(2, input$mean_2)
        tab <- data.frame(x = x, y = y, z = c("hello", "%%eta%%%%epsilon%%"))
        rownames(tab) <- c("%%alpha%%", "%%beta%%")
        tab
      }, rownames = TRUE)
      
    } # Closes server
    
    js <- "
    $(document).on('shiny:value', function(event) {
      if((/table_1$/).test(event.name) || (/table_2$/).test(event.name)){
        var matches = event.value.match(/(%%+[^%]+%%)/g);
        var newvalue = event.value;
        for(var i=0; i<matches.length; i++){
          var code = '\\\\' + matches[i].slice(2,-2);
          newvalue = newvalue.replace(matches[i], katex.renderToString(code));
        }
        event.value = newvalue;
      }
    })
    "
    
    ui = dashboardPage(
      
      header = dashboardHeader(),
      
      body = dashboardBody(
        
        tags$head(
          tags$link(rel="stylesheet", href="https://cdn.jsdelivr.net/npm/katex@0.10.0-beta/dist/katex.min.css", integrity="sha384-9tPv11A+glH/on/wEu99NVwDPwkMQESOocs/ZGXPoIiLE8MU/qkqUcZ3zzL+6DuH", crossorigin="anonymous"),
          tags$script(src="https://cdn.jsdelivr.net/npm/katex@0.10.0-beta/dist/katex.min.js", integrity="sha384-U8Vrjwb8fuHMt6ewaCy8uqeUXv4oitYACKdB0VziCerzt011iQ/0TqlSlv8MReCm", crossorigin="anonymous"),
          tags$script(HTML(js))
        ),
        
        tabItems(
          
          tabItem(tabName = "table_1",
                  table1UI(id = "table1id")),
          
          tabItem(tabName = "table_2",
                  table2UI(id = "table2id"))
          
        ) # Closes tabItems
        
      ), # Closes dashboard body
      
      sidebar = dashboardSidebar(
        
        width = 272.25, # Header is 230px button is 42.5px
        
        minified = FALSE,
        
        sidebarMenu(
          menuItem("Table 1", tabName = "table_1", icon = icon("chalkboard-teacher")),
          menuItem("Table 2", tabName = "table_2", icon = icon("chalkboard-teacher"))
        )
        
      )
      
    ) # Closes UI
    
    server = function(input, output, session) { 
      
      callModule(module = table1,
                 id = "table1id")
      
      callModule(module = table2,
                 id = "table2id")
      
    } # Closes Server
    
    shinyApp(ui, server)
    

    【讨论】:

    • 嗨@Stéphane Laurent,谢谢!这暴露了另一个问题。当它们被包装在模块中的 ns() 中时,是否可以引用 event.name,即 table_1 或 table_2(参见原始帖子中的 reprex)?再次感谢!
    • @ZekeMarshall ns("table_2") 返回"namespace-table2"。最简单的方法是if((/table_2$/).test(event.name))。在 JavaScript 中,/table_2$/ 是一个正则表达式,它代表所有以table_2 结尾的字符串。
    • 嗨@Stéphane Laurent 再次感谢!在 reprex 的上下文中这将如何工作?我尝试将if(event.name === 'table_1') 替换为if((/table_1$/).test(event.name)),并将'table_1' 替换为'/table_1$/',但两者都不起作用。再次感谢您迄今为止的帮助!
    • 感谢@Stéphane Laurent!这非常有效!
    猜你喜欢
    • 2022-12-23
    • 2023-02-20
    • 2019-03-19
    • 2019-03-04
    • 2020-11-08
    • 1970-01-01
    • 1970-01-01
    • 2018-07-08
    • 2019-03-07
    相关资源
    最近更新 更多