0

I try to launch a dataframe in a shiny dashboard within a for-loop. My purpose is to update the values in the dataframe every iteration and show this within the shiny dashboard. For some reason the shiny dashboard is not launched at all. Although if I select the line shinyApp(ui, server) and press Enter, the dashboard launches correctly. What can be the reason why the dashboard is not launching within the loop? Thanks a lot!

library(shiny)
library(shinydashboard)
library(DT)

# my dataframe:
letter <- c("a","b")
number <- c(1,2)
df <- data.frame(letter, number)

# sidebar
sidebar <- dashboardSidebar()

# body
body <- dashboardBody(
  fluidRow(
    box(width = 6, 
        DT::dataTableOutput("mytable")
    )
  )
)

# ui
ui <- dashboardPage(dashboardHeader(title = "hello world"),
                    sidebar,
                    body
)

# server logic
server <- function(input, output) {
  output$mytable = DT::renderDataTable({
    df
  })
}

#launch shiny app:
for (t in 1:3) {

  df[1,2] <- t
  shinyApp(ui, server)

}

EDIT1

I have tried the replace the server-code with the code below although this does not give a dataframe in Shiny:

# server logic
server <- function(input, output) {
  # my dataframe:
  
  df <- reactive(
    for (t in 1:300) {
    data.frame(
      letter=c("a","b"),
      number=c(1,t)
    )}
    )
  
  output$mytable <- DT::renderDataTable({
    df()
  })
}
user2165379
  • 445
  • 4
  • 20
  • I think you have the wrong idea, instead of spaning multiple dashboards, you should use reactive values INSIDE the shinyapp – user12256545 Mar 24 '23 at 15:32

1 Answers1

0

Using a for loop in the way you describe in your example wont work, since the for loop would spawn multiple shiny apps, but what i assume that you want instead is to simply update your shinyapp. In this specific case the value at the dataframe at [1,2] . This is way easier to implement with a simple counter than with a loop.

# sidebar
sidebar <- dashboardSidebar()

# body
body <- dashboardBody(
  fluidRow(
    box(width = 6, 
        inputPanel(numericInput("NUM","iteration",value=1)),
        DT::dataTableOutput("mytable")
    )
  )
)

# ui
ui <- dashboardPage(dashboardHeader(title = "hello world"),
                    sidebar,
                    body
)

# server logic
server <- function(input, output) {
  # my dataframe:
  df <- reactive(
    data.frame(
      letter=c("a","b"),
      number=c(1,input$NUM)
      ))

  output$mytable <- DT::renderDataTable({
    df()
  })
}

shinyApp(ui, server)

See how the df is created as a reactive object, thus you can call it like a function: df()instead of df in the render function.

df[1,2] is simply assinged to input$NUM , the counter set up in the UI.

I hope this helps and answers your question, if not, feel free to update your Question or leave a comment.

user12256545
  • 2,755
  • 4
  • 14
  • 28
  • @ user 12256545 Thank you. I call an API every second within a loop which updates a dataframe which I would like to see changing. There is no interactivity, it just runs by itself. (The reason to choose Shiny is just to let the output look nicer compared to the console.) In your code the number=input$NUM is set by the user. Maybe I can assign all my code within the loop to number=c(1,input$NUM) although then I have all my code within a function. Is there a way to have the loop with my code which is updating the dataframe outside of the server-function? Thanks a lot! – user2165379 Mar 25 '23 at 11:44
  • I used the user input to simulate a change in the df value. this is not strictly about interactivity but to demonstrate reactivity, which you will need to incorporate if you have an object that needs to get updated. It is not totally clear to me what the for loop accomplishes, hoever I will change the example adding an API call. All application logic has to be in the server function of the app or a module . – user12256545 Mar 25 '23 at 12:45
  • within the loop the api is called and the json-response is processed and stored in a dataframe. The loop iterates every second and update the dataframe with the new input from the api call. For my understanding it is enough to put the loop mentioned above inside the server. – user2165379 Mar 25 '23 at 13:56