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

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

How do I reuse a user element in R shiny?

问题

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

服务器/用户界面

  1. library(shiny)
  2. ui <- navbarPage(
  3. title="一些标题",
  4. tabPanel(
  5. title="选项卡1",
  6. sidebarLayout(
  7. # 这是我想要重用的元素,请参见第二个选项卡面板
  8. sidebarPanel(radioButtons(inputId="button1", label="选择", choices=c("1", "2"))),
  9. mainPanel(uiOutput("output1"))
  10. )
  11. ),
  12. tabPanel(
  13. title="选项卡2",
  14. sidebarLayout(
  15. sidebarPanel(radioButtons(inputId="button1", label="选择", choices=c("1", "2"))),
  16. mainPanel(uiOutput("output2"))
  17. )
  18. )
  19. )
  20. server <- function(input, output, session) {
  21. output$output1 <- renderText("文本1")
  22. output$output2 <- renderText("文本2")
  23. }
  24. shinyApp(ui=ui, server=server)

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

模块 module.R

  1. library(shiny)
  2. samplePanel <- function(id) {
  3. ns <- NS(id)
  4. sidebarPanel(
  5. radioButtons(inputId="button1", label="选择", choices=c("1", "2")),
  6. textOutput("sample_text")
  7. )
  8. }
  9. sampleModule <- function(input, output, session) {
  10. output$sample_text <- renderText("示例文本")
  11. }

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

  1. source("module.R")
  2. library(shiny)
  3. ui <- navbarPage(
  4. title="一些标题",
  5. tabPanel(
  6. title="选项卡1",
  7. sidebarLayout(
  8. samplePanel("moduleId"),
  9. mainPanel(uiOutput("output1"))
  10. )
  11. ),
  12. tabPanel(
  13. title="选项卡2",
  14. sidebarLayout(
  15. samplePanel("moduleId"),
  16. mainPanel(uiOutput("output2"))
  17. )
  18. )
  19. )
  20. server <- function(input, output, session) {
  21. callModule(sampleModule, "moduleId")
  22. output$output1 <- renderText("文本1")
  23. output$output2 <- renderText("文本2")
  24. }
  25. 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

  1. library(shiny)
  2. ui &lt;- navbarPage(
  3. title=&quot;some title&quot;,
  4. tabPanel(
  5. title=&quot;Tab 1&quot;,
  6. sidebarLayout(
  7. # This is the element I want to reuse, see second tabPanel
  8. sidebarPanel(radioButtons(inputId=&quot;button1&quot;, label=&quot;Choose&quot;, choices=c(&quot;1&quot;, &quot;2&quot;))),
  9. mainPanel(uiOutput(&quot;output1&quot;))
  10. )
  11. ),
  12. tabPanel(
  13. title=&quot;Tab 2&quot;,
  14. sidebarLayout(
  15. sidebarPanel(radioButtons(inputId=&quot;button1&quot;, label=&quot;Choose&quot;, choices=c(&quot;1&quot;, &quot;2&quot;))),
  16. mainPanel(uiOutput(&quot;output2&quot;))
  17. )
  18. )
  19. )
  20. server &lt;- function(input, output, session) {
  21. output$output1 &lt;- renderText(&quot;Text 1&quot;)
  22. output$output2 &lt;- renderText(&quot;Text 2&quot;)
  23. }
  24. 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

  1. library(shiny)
  2. samplePanel &lt;- function(id) {
  3. ns &lt;- NS(id)
  4. sidebarPanel(
  5. radioButtons(inputId=&quot;button1&quot;, label=&quot;Choose&quot;, choices=c(&quot;1&quot;, &quot;2&quot;)),
  6. textOutput(&quot;sample_text&quot;)
  7. )
  8. }
  9. sampleModule &lt;- function(input, output, session) {
  10. output$sample_text &lt;- renderText(&quot;Sample text&quot;)
  11. }

New Server/UI main script

  1. source(&quot;module.R&quot;)
  2. library(shiny)
  3. ui &lt;- navbarPage(
  4. title=&quot;some title&quot;,
  5. tabPanel(
  6. title=&quot;Tab 1&quot;,
  7. sidebarLayout(
  8. samplePanel(&quot;moduleId&quot;),
  9. mainPanel(uiOutput(&quot;output1&quot;))
  10. )
  11. ),
  12. tabPanel(
  13. title=&quot;Tab 2&quot;,
  14. sidebarLayout(
  15. samplePanel(&quot;moduleId&quot;),
  16. mainPanel(uiOutput(&quot;output2&quot;))
  17. )
  18. )
  19. )
  20. server &lt;- function(input, output, session) {
  21. callModule(sampleModule, &quot;moduleId&quot;)
  22. output$output1 &lt;- renderText(&quot;Text 1&quot;)
  23. output$output2 &lt;- renderText(&quot;Text 2&quot;)
  24. }
  25. 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

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

  1. library(shiny)
  2. samplePanel <- function(id) {
  3. ns <- NS(id)
  4. sidebarPanel(
  5. radioButtons(inputId=ns("button1"), label="选择", choices=c("1", "2")),
  6. textOutput(ns("sample_text"))
  7. )
  8. }
  9. sampleModule <- function(input, output, session) {
  10. output$sample_text <- renderText("示例文本")
  11. }
  12. ui <- navbarPage(
  13. title="一些标题",
  14. tabPanel(
  15. title="选项卡1",
  16. sidebarLayout(
  17. samplePanel("moduleId1"),
  18. mainPanel(uiOutput("output1"))
  19. )
  20. ),
  21. tabPanel(
  22. title="选项卡2",
  23. sidebarLayout(
  24. samplePanel("moduleId2"),
  25. mainPanel(uiOutput("output2"))
  26. )
  27. )
  28. )
  29. server <- function(input, output, session) {
  30. callModule(sampleModule, "moduleId1")
  31. callModule(sampleModule, "moduleId2")
  32. output$output1 <- renderText("文本1")
  33. output$output2 <- renderText("文本2")
  34. }
  35. shinyApp(ui=ui, server=server)

编辑

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

  1. library(shiny)
  2. samplePanel <- function(id) {
  3. ns <- NS(id)
  4. sidebarPanel(
  5. radioButtons(inputId=ns("button1"), label="选择", choices=c("1", "2")),
  6. textOutput(ns("sample_text"))
  7. )
  8. }
  9. sampleModule <- function(input, output, session) {
  10. output$sample_text <- renderText("示例文本")
  11. }
  12. ui <- navbarPage(
  13. title="一些标题",
  14. samplePanel("moduleId1"),
  15. mainPanel(
  16. tabsetPanel(
  17. tabPanel(
  18. title="选项卡1",
  19. uiOutput("output1")
  20. ),
  21. tabPanel(
  22. title="选项卡2",
  23. uiOutput("output2")
  24. )
  25. )
  26. )
  27. )
  28. server <- function(input, output, session) {
  29. callModule(sampleModule, "moduleId1")
  30. output$output1 <- renderText("文本1")
  31. output$output2 <- renderText("文本2")
  32. }
  33. shinyApp(ui=ui, server=server)

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

英文:

Does this give you something close to what you want?

  1. library(shiny)
  2. samplePanel &lt;- function(id) {
  3. ns &lt;- NS(id)
  4. sidebarPanel(
  5. radioButtons(inputId=ns(&quot;button1&quot;), label=&quot;Choose&quot;, choices=c(&quot;1&quot;, &quot;2&quot;)),
  6. textOutput(ns(&quot;sample_text&quot;))
  7. )
  8. }
  9. sampleModule &lt;- function(input, output, session) {
  10. output$sample_text &lt;- renderText(&quot;Sample text&quot;)
  11. }
  12. ui &lt;- navbarPage(
  13. title=&quot;some title&quot;,
  14. tabPanel(
  15. title=&quot;Tab 1&quot;,
  16. sidebarLayout(
  17. samplePanel(&quot;moduleId1&quot;),
  18. mainPanel(uiOutput(&quot;output1&quot;))
  19. )
  20. ),
  21. tabPanel(
  22. title=&quot;Tab 2&quot;,
  23. sidebarLayout(
  24. samplePanel(&quot;moduleId2&quot;),
  25. mainPanel(uiOutput(&quot;output2&quot;))
  26. )
  27. )
  28. )
  29. server &lt;- function(input, output, session) {
  30. callModule(sampleModule, &quot;moduleId1&quot;)
  31. callModule(sampleModule, &quot;moduleId2&quot;)
  32. output$output1 &lt;- renderText(&quot;Text 1&quot;)
  33. output$output2 &lt;- renderText(&quot;Text 2&quot;)
  34. }
  35. 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.

  1. library(shiny)
  2. samplePanel &lt;- function(id) {
  3. ns &lt;- NS(id)
  4. sidebarPanel(
  5. radioButtons(inputId=ns(&quot;button1&quot;), label=&quot;Choose&quot;, choices=c(&quot;1&quot;, &quot;2&quot;)),
  6. textOutput(ns(&quot;sample_text&quot;))
  7. )
  8. }
  9. sampleModule &lt;- function(input, output, session) {
  10. output$sample_text &lt;- renderText(&quot;Sample text&quot;)
  11. }
  12. ui &lt;- navbarPage(
  13. title=&quot;some title&quot;,
  14. samplePanel(&quot;moduleId1&quot;),
  15. mainPanel(
  16. tabsetPanel(
  17. tabPanel(
  18. title=&quot;Tab 1&quot;,
  19. uiOutput(&quot;output1&quot;)
  20. ),
  21. tabPanel(
  22. title=&quot;Tab 2&quot;,
  23. uiOutput(&quot;output2&quot;)
  24. )
  25. )
  26. )
  27. )
  28. server &lt;- function(input, output, session) {
  29. callModule(sampleModule, &quot;moduleId1&quot;)
  30. output$output1 &lt;- renderText(&quot;Text 1&quot;)
  31. output$output2 &lt;- renderText(&quot;Text 2&quot;)
  32. }
  33. 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:

确定