firmo23
firmo23

Reputation: 8404

How to stop recreating a dataset at each rendering of a shiny app

I have a simple shiny app in which I use a selectInput() "Label" to select a Label from the datatable and then change its name with textInput() "Change to". The problem is that I want the application to keep all the name changes I make and not returning to the default name when I choose another Label. I think the problem is that the DF exists only within rt4 function and not outside it so it's recreated at each rendering.

 #ui.r
    navbarPage(
      "Application",
      tabPanel("General",
               sidebarLayout(

                 sidebarPanel(
                   uiOutput("book3"),
                   uiOutput("book6")
                  ),
                 mainPanel(

                   DT::dataTableOutput("hot3")

                 )
               )))
    #server.r
    library(shiny)
    library(DT)
    server <- function(input, output,session) {



      output$book3<-renderUI({
        selectInput("bk3", 
                    "Label", 
                    choices=(paste("Test",1:5)))
      })

      output$book6<-renderUI({
        textInput("bk6", "Change to",
                  value=NULL
        )
      })

      rt4<-reactive({
        if(is.null(input$bk6)|input$bk6==""){
            DF=data.frame(
              Test=paste(1:5),
              Label=paste("Test",1:5),
              stringsAsFactors = FALSE)
        }
        else{
          DF[DF==input$bk3]<-input$bk6
        }
        DF

      })

      output$hot3 <-DT::renderDataTable(
        rt4(),
        rownames= FALSE

      )

    }

Upvotes: 0

Views: 57

Answers (1)

Mike Badescu
Mike Badescu

Reputation: 165

Important changes:
- as you expected, DF is defined once, in the server, see shiny scoping rules
- use <<- to modify the global (server) DF
- use isolate() to react only to the change of input$bk6

library(shiny)
library(DT)

ui <- navbarPage(
    "Application",
    tabPanel("General",
             sidebarLayout(
                 sidebarPanel(
                     uiOutput("book3"),
                     uiOutput("book6")
                 ),
                 mainPanel(
                     DT::dataTableOutput("hot3")
                 )
             )))

server <- function(input, output,session) {

    DF <- data.frame(
        Test=paste(1:5),
        Label=paste("Test",1:5),
        stringsAsFactors = FALSE)

    output$book3<-renderUI({
        selectInput("bk3", "Label",  choices=(paste("Test",1:5)))
    })

    output$book6<-renderUI({
        textInput("bk6", "Change to", value=NULL)
    })

    rt4<-reactive({
        if(!is.null(input$bk6) && input$bk6!=""){
            DF[DF$Label==isolate(input$bk3), "Test"] <<- input$bk6
        }
        DF
    })

    output$hot3 <-DT::renderDataTable(
        rt4(),
        rownames= FALSE

    )
}

shinyApp(ui, server)

Upvotes: 1

Related Questions