尝试使用 actionButton 获取嵌套在随机选项卡中的下一个随机图像

Trying to use an actionButton to get next random image nested within random tab

问题

我正在开发一个闪亮的应用程序,其中包含一份关于狗的品种和生活空间的问卷。对于每个犬种的问题,每个犬种都以随机顺序出现在一个选项卡中,在这些选项卡中,我显示了不同的房子,您可以在这些房子里养这些犬种。

主要思想是随机化犬种(按选项卡)和嵌套在该选项卡中的每种住房可能性。

到目前为止我有什么

这是我迄今为止在 working shiny app and all the files and scripts are in this github repository 中最有效的示例,因此您可以克隆它来测试所有示例代码

在此应用程序中,选项卡确实以随机顺序(按品种)显示。第一个房子选项也显示得很好,我的想法是当你按下 next house 操作按钮时,它会显示下一个随机房子而不重复(重要的是回答的人看不到提前下家,以免影响)

我尝试了两种不同的方法来解决这个问题,包括在文件夹 FirstTrySecondTry 中的 github 存储库中。

第一次尝试

这是正在运行的 shiny 应用程序,这是它的代码,在此 link and with the code in this link

中运行

这是 ui 的代码,它非常简单,只是一个带有 uiOutput mytabs 的选项卡面板,其中包含所有选项卡:

library(shiny)

shinyApp(
    ui = tagList(
        navbarPage("",

                   tabPanel("DogImages",
                            fluidRow(
                                column(width = 6,
                                       uiOutput('mytabs')
                                ) )

                   )#cerrado tab panel 2

        ) #cerrado de navbar Panel    

    ), #cerrado ui

然后服务器就是所有魔法发生的地方


    server <- function(input, output) {


        #####################################
        # Tabs breeds

        ## This renderUI generates each tab with a lapply
        output$mytabs = renderUI({

            ## I have three breeds
            Breeds <- c(1:3)

            ## And then create a random order of them
            Random <- sample(Breeds, 3)

            #### And now loop through each random breed
            myTabs = lapply(Random, function(i){

                ### Starts with the first random breed
                tabPanel(paste("Breed", i),

                         ###
                         fluidPage(
                             fluidRow(
                                 column(6,
                                        wellPanel(
                                     ###Here it sources random breed i    
                                            img(src = paste0("Dog",i, ".jpg"), height = 300, width = 300))),
                                 ##then within that I want to have the
                                 ##Random houses but here is where I run 
                                 ##into problems
                                 renderUI({
                                     ##Starting with random habitats
                                     Habitats <- c(1:3)
                                     RandomH <- sample(Habitats, 3)


                                     ## The idea is that I use this new button to show the next house
                                     column(6,actionButton("New_Button", "Next house"),
                                            wellPanel(
                                                uiOutput(paste0("PlotHouse",RandomH[1])))                                     )

                                 })
                             )
                         ))
                ####
            })


            do.call(tabsetPanel, myTabs)
        })

这只是每个房子的来源和服务器关闭和闪亮:


        output$PlotHouse1 <- renderUI({
            img(src = "House1.jpg", height = 300, width = 300)
        })

        output$PlotHouse2 <- renderUI({
            img(src = "House2.jpg", height = 300, width = 300)
        })

        output$PlotHouse3 <- renderUI({
            img(src = "House3.jpg", height = 300, width = 300)
        })


    }

) #Close shiny app

所以这适用于犬种但不适用于 not ,我必须点击 下一步按钮 来显示下一个随机房子,这就是我在文件夹 SecondTry

第二次尝试

对于这个,我更改了 lapply:

中第二个 renderUI 中的代码
renderUI({Habitats <- c(1:3)
          RandomH <- sample(Habitats, 3)
           ### Here I add the reactive value j = 1 to move the RandomH along
          Values <- reactiveValues(j = 1)
         ###This is to show j just for the question
          output$Numb <- renderText(Values$j)
    ### Here I state that every time I press new button it adds 1 to j
          observe({input$New_Button
                   isolate(Values$j <- Values$j + 1)
                   })
          ## and this is the action button for next house  
          column(6,actionButton("New_Button", "Next house"),
                 textOutput("Numb"),
                  ## Here I say show me img PlotHouse[j]
                 wellPanel(uiOutput(paste0("PlotHouse",RandomH[Values$j])))
                           )

           })

预期的解决方案

只是当我按下下一个房子按钮时,我看到了下一个随机房子

除了将计数存储在反应值中之外,主要的挑战是区分选项卡:两种方式来自两种想法。

  • 使用模块
  • 监听选项卡更改。

要计算点击次数,只需使用 reactiveValues()

global <- reactiveValues(nr = 1)    

observeEvent(input$New_Button1, {
  global$nr <- min(global$nr + 1, maxHouseNr)
})

为了在切换到您想要监听选项卡更改的新选项卡时重置计数器。您可以给 tabsetPanel() 一个 ID 并在 input$ID.

上收听

设置 ID:

do.call(tabsetPanel, c(id = "whichTab", myTabs))

监听选项卡更改:

observeEvent(input$whichTab, {
  global$nr <- 1 
})

代码:

library(shiny)
maxHouseNr <- 3
Habitats <- 1:maxHouseNr
RandomH <-lapply(rep(maxHouseNr, 3), sample, size = maxHouseNr, replace = FALSE)


shinyApp(
  ui = tagList(
    navbarPage("",

               tabPanel("DogImages",
                        fluidRow(
                          column(width = 6,
                                 uiOutput('mytabs')
                          ) )

               )#cerrado tab panel 2

    ) #cerrado de navbar Panel    

  ), #cerrado ui

  server <- function(input, output) {


    global <- reactiveValues(nr = 1)    

    observeEvent(input$whichTab, {
      global$nr <- 1 
    })

    observeEvent(input$New_Button1, {
      global$nr <- min(global$nr + 1, maxHouseNr)
    })

    observeEvent(input$New_Button2, {
      global$nr <- min(global$nr + 1, maxHouseNr)
    })

    observeEvent(input$New_Button3, {
      global$nr <- min(global$nr + 1, maxHouseNr)
    })


    #####################################
    # Tabs breeds

    output$mytabs = renderUI({
      Breeds <- c(1:3)
      Random <- sample(Breeds, 3)
      myTabs = lapply(Random, function(i){


        tabPanel(paste("Breed", i),

                 ###
                 fluidPage(
                   fluidRow(
                     column(6,
                            wellPanel(
                              img(src = paste0("Dog",i, ".jpg"), height = 300, width = 300))),
                     renderUI({

                       column(6, actionButton(inputId = paste0("New_Button", i), "Next house"),
                              wellPanel(
                                uiOutput(paste0("PlotHouse", i)))
                       )

                     })
                   )
                 ))
        ####
      })


      do.call(tabsetPanel, c(id = "whichTab", myTabs))
    })

    output$PlotHouse1 <- renderUI({
      img(src = paste0("House", RandomH[[1]][global$nr],".jpg"), height = 300, width = 300)
    })

    output$PlotHouse2 <- renderUI({

      img(src = paste0("House", RandomH[[2]][global$nr],".jpg"), height = 300, width = 300)
    })

    output$PlotHouse3 <- renderUI({
      img(src = paste0("House", RandomH[[3]][global$nr],".jpg"), height = 300, width = 300)
    })


  }

) #cerrado de shiny

只需将随机顺序转换为反应值并在反应环境中通过按钮触发计算 (ojala sea esto lo que quieres)

library(shiny)

shinyApp(
    ui = tagList(
        navbarPage("",

                   tabPanel("DogImages",
                            fluidRow(
                                column(width = 6,
                                       uiOutput('mytabs')
                                ) )

                   )#cerrado tab panel 2

        ) #cerrado de navbar Panel    

    ), #cerrado ui

    server <- function(input, output) {

        Breeds <- c(1:3)
        Values =reactiveValues()

        #####################################
        # Tabs breeds
        observe({
            input$New_Button
            Values$Random <- sample(Breeds, 3)
        })

        output$mytabs = renderUI({
            myTabs = lapply(Values$Random, function(i){


                tabPanel(paste("Breed", i),

                         ###
                         fluidPage(
                             fluidRow(
                                 column(6,
                                        wellPanel(
                                            img(src = paste0("Dog",i, ".jpg"), height = 300, width = 300))),
                                 renderUI({
                                     Habitats <- c(1:3)
                                     RandomH <- sample(Habitats, 3)

                                     column(6,actionButton("New_Button", "Next house"),
                                            wellPanel(
                                                uiOutput(paste0("PlotHouse",RandomH[1])))
                                     )

                                 })
                             )
                         ))
                ####
            })


            do.call(tabsetPanel, myTabs)
        })

        output$PlotHouse1 <- renderUI({
            img(src = "House1.jpg", height = 300, width = 300)
        })

        output$PlotHouse2 <- renderUI({
            img(src = "House2.jpg", height = 300, width = 300)
        })

        output$PlotHouse3 <- renderUI({
            img(src = "House3.jpg", height = 300, width = 300)
        })


    }

) #cerrado de shiny