如何在R Shiny中重用用户元素?

huangapple go评论88阅读模式
英文:

How do I reuse a user element in R shiny?

问题

我正在编写一个Shiny应用程序,其中包含一个sidebarPanel,其中包含各种交互式用户元素。这个sidebarPanel嵌入在UI中,如下所示:

服务器/用户界面

library(shiny)

ui <- navbarPage(
  title="一些标题",
  tabPanel(
    title="选项卡1",
    sidebarLayout(
      # 这是我想要重用的元素,请参见第二个选项卡面板
      sidebarPanel(radioButtons(inputId="button1", label="选择", choices=c("1", "2"))),
      mainPanel(uiOutput("output1"))
    )
  ),
  tabPanel(
    title="选项卡2",
    sidebarLayout(
      sidebarPanel(radioButtons(inputId="button1", label="选择", choices=c("1", "2"))),
      mainPanel(uiOutput("output2"))
    )
  )
)
  
server <- function(input, output, session) {
  output$output1 <- renderText("文本1")
  output$output2 <- renderText("文本2")
}

shinyApp(ui=ui, server=server)

我尝试创建一个模块,例如https://stackoverflow.com/questions/60756339/translate-shiny-app-using-shiny-i18n-in-modules中所做的方式。

模块 module.R

library(shiny)

samplePanel <- function(id) {
  ns <- NS(id)
  sidebarPanel(
    radioButtons(inputId="button1", label="选择", choices=c("1", "2")),
    textOutput("sample_text")
  )
}

sampleModule <- function(input, output, session) {
  output$sample_text <- renderText("示例文本")
}

新的服务器/用户界面主脚本

source("module.R")

library(shiny)

ui <- navbarPage(
  title="一些标题",
  tabPanel(
    title="选项卡1",
    sidebarLayout(
      samplePanel("moduleId"),
      mainPanel(uiOutput("output1"))
    )
  ),
  tabPanel(
    title="选项卡2",
    sidebarLayout(
      samplePanel("moduleId"),
      mainPanel(uiOutput("output2"))
    )
  )
)

server <- function(input, output, session) {
  callModule(sampleModule, "moduleId")
  output$output1 <- renderText("文本1")
  output$output2 <- renderText("文本2")
}

shinyApp(ui=ui, server=server)

关于将Shiny代码模块化的问题,我不明白的是为什么我的samplePanel甚至不显示我想要显示的sample_text。编辑:已修复有关在sidebarPanel中呈现文本的微不足道的错误。

英文:

I am writing a shiny app where I have a sidebarPanel containing various interactive user elements. This sidebarPanel is embedded in the ui in such a way:

Server/UI

library(shiny)

ui &lt;- navbarPage(
  title=&quot;some title&quot;,
  tabPanel(
    title=&quot;Tab 1&quot;,
    sidebarLayout(
      # This is the element I want to reuse, see second tabPanel
      sidebarPanel(radioButtons(inputId=&quot;button1&quot;, label=&quot;Choose&quot;, choices=c(&quot;1&quot;, &quot;2&quot;))),
      mainPanel(uiOutput(&quot;output1&quot;))
    )
  ),
  tabPanel(
    title=&quot;Tab 2&quot;,
    sidebarLayout(
      sidebarPanel(radioButtons(inputId=&quot;button1&quot;, label=&quot;Choose&quot;, choices=c(&quot;1&quot;, &quot;2&quot;))),
      mainPanel(uiOutput(&quot;output2&quot;))
    )
  )
)
  
    
server &lt;- function(input, output, session) {
  output$output1 &lt;- renderText(&quot;Text 1&quot;)
  output$output2 &lt;- renderText(&quot;Text 2&quot;)
}

shinyApp(ui=ui, server=server)

I have tried creating a module such as they did in https://stackoverflow.com/questions/60756339/translate-shiny-app-using-shiny-i18n-in-modules

Module module.R

library(shiny)

samplePanel &lt;- function(id) {
  ns &lt;- NS(id)
  sidebarPanel(
    radioButtons(inputId=&quot;button1&quot;, label=&quot;Choose&quot;, choices=c(&quot;1&quot;, &quot;2&quot;)),
    textOutput(&quot;sample_text&quot;)
  )
}

sampleModule &lt;- function(input, output, session) {
  output$sample_text &lt;- renderText(&quot;Sample text&quot;)
}

New Server/UI main script

source(&quot;module.R&quot;)

library(shiny)

ui &lt;- navbarPage(
  title=&quot;some title&quot;,
  tabPanel(
    title=&quot;Tab 1&quot;,
    sidebarLayout(
      samplePanel(&quot;moduleId&quot;),
      mainPanel(uiOutput(&quot;output1&quot;))
    )
  ),
  tabPanel(
    title=&quot;Tab 2&quot;,
    sidebarLayout(
      samplePanel(&quot;moduleId&quot;),
      mainPanel(uiOutput(&quot;output2&quot;))
    )
  )
)


server &lt;- function(input, output, session) {
  callModule(sampleModule, &quot;moduleId&quot;)
  output$output1 &lt;- renderText(&quot;Text 1&quot;)
  output$output2 &lt;- renderText(&quot;Text 2&quot;)
}

shinyApp(ui=ui, server=server)

What is it I don't understand about modularizing shiny code? One thing that surprises me is that my samplePanel doesn't even show the sample_text I want it to show.

Edit: Fixed the trivial error regarding text rendering in the sidebarPanel.

答案1

得分: 1

这个布局是否接近您想要的效果?

library(shiny)

samplePanel <- function(id) {
  ns <- NS(id)
  sidebarPanel(
    radioButtons(inputId=ns("button1"), label="选择", choices=c("1", "2")),
    textOutput(ns("sample_text"))
  )
}

sampleModule <- function(input, output, session) {
  output$sample_text <- renderText("示例文本")
}

ui <- navbarPage(
  title="一些标题",
  tabPanel(
    title="选项卡1",
    sidebarLayout(
      samplePanel("moduleId1"),
      mainPanel(uiOutput("output1"))
    )
  ),
  tabPanel(
    title="选项卡2",
    sidebarLayout(
      samplePanel("moduleId2"),
      mainPanel(uiOutput("output2"))
    )
  )
)

server <- function(input, output, session) {
  callModule(sampleModule, "moduleId1")
  callModule(sampleModule, "moduleId2")
  output$output1 <- renderText("文本1")
  output$output2 <- renderText("文本2")
}

shinyApp(ui=ui, server=server)

编辑

根据评论中的讨论,这个布局将模块从tabPanel的侧边栏移动到页面侧边栏,这意味着一个单一的实例将对每个tabPanel都是共用的。因为现在只有一个实例,可能不需要使用模块。

library(shiny)

samplePanel <- function(id) {
  ns <- NS(id)
  sidebarPanel(
    radioButtons(inputId=ns("button1"), label="选择", choices=c("1", "2")),
    textOutput(ns("sample_text"))
  )
}

sampleModule <- function(input, output, session) {
  output$sample_text <- renderText("示例文本")
}

ui <- navbarPage(
  title="一些标题",
  samplePanel("moduleId1"),
  mainPanel(
    tabsetPanel(
      tabPanel(
        title="选项卡1",
        uiOutput("output1")
      ),
      tabPanel(
        title="选项卡2",
        uiOutput("output2")
      )
    )
  )
)

server <- function(input, output, session) {
  callModule(sampleModule, "moduleId1")
  output$output1 <- renderText("文本1")
  output$output2 <- renderText("文本2")
}

shinyApp(ui=ui, server=server)

如果这个回答有用,请接受它,而不仅仅是点赞。点击接近点赞和反对按钮的对勾标记。谢谢。

英文:

Does this give you something close to what you want?

library(shiny)

samplePanel &lt;- function(id) {
  ns &lt;- NS(id)
  sidebarPanel(
    radioButtons(inputId=ns(&quot;button1&quot;), label=&quot;Choose&quot;, choices=c(&quot;1&quot;, &quot;2&quot;)),
    textOutput(ns(&quot;sample_text&quot;))
  )
}

sampleModule &lt;- function(input, output, session) {
  output$sample_text &lt;- renderText(&quot;Sample text&quot;)
}

ui &lt;- navbarPage(
  title=&quot;some title&quot;,
  tabPanel(
    title=&quot;Tab 1&quot;,
    sidebarLayout(
      samplePanel(&quot;moduleId1&quot;),
      mainPanel(uiOutput(&quot;output1&quot;))
    )
  ),
  tabPanel(
    title=&quot;Tab 2&quot;,
    sidebarLayout(
      samplePanel(&quot;moduleId2&quot;),
      mainPanel(uiOutput(&quot;output2&quot;))
    )
  )
)

server &lt;- function(input, output, session) {
  callModule(sampleModule, &quot;moduleId1&quot;)
  callModule(sampleModule, &quot;moduleId2&quot;)
  output$output1 &lt;- renderText(&quot;Text 1&quot;)
  output$output2 &lt;- renderText(&quot;Text 2&quot;)
}

shinyApp(ui=ui, server=server)

EDIT

In response to discussion in comments, this layout moves the module from the tabPanel sidebar to the page sidebar, meaning that a single instance is common to each of the tabPanels. As there's now only a single instance, there may not be any need to use a module.

library(shiny)

samplePanel &lt;- function(id) {
  ns &lt;- NS(id)
  sidebarPanel(
    radioButtons(inputId=ns(&quot;button1&quot;), label=&quot;Choose&quot;, choices=c(&quot;1&quot;, &quot;2&quot;)),
    textOutput(ns(&quot;sample_text&quot;))
  )
}

sampleModule &lt;- function(input, output, session) {
  output$sample_text &lt;- renderText(&quot;Sample text&quot;)
}

ui &lt;- navbarPage(
  title=&quot;some title&quot;,
    samplePanel(&quot;moduleId1&quot;),
    mainPanel(
      tabsetPanel(
      tabPanel(
        title=&quot;Tab 1&quot;,
        uiOutput(&quot;output1&quot;)
      ),
      tabPanel(
        title=&quot;Tab 2&quot;,
        uiOutput(&quot;output2&quot;)
      )
    )
  )
)

server &lt;- function(input, output, session) {
  callModule(sampleModule, &quot;moduleId1&quot;)
  output$output1 &lt;- renderText(&quot;Text 1&quot;)
  output$output2 &lt;- renderText(&quot;Text 2&quot;)
}

shinyApp(ui=ui, server=server)

Please accept this answer if it is useful, rather than merely upvoting it. Click the tick mark close to the up- and downvote buttons. Thank you.

huangapple
  • 本文由 发表于 2023年7月18日 15:31:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76710433.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定