2

Currently, I have function that launches shiny app, gets user inputs, saves to global variable once person close shiny window.

I'd like to add ActionButton to close shiny instead of person having to close window

The ActionButton closes shiny --- but it bypasses the code in session$onSessionEnded

After running Shiny terminal shows it scanned in values of color palette, but global variable of cherrypickedpalette is NULL

> CherryPickPalette("BiryaniRice","Kulfi","Haveli2")

Listening on http://127.0.0.1:5345
Read 8 items
> cherrypickedpalette
NULL

Here is the entire R script

Calling function

CherryPickPalette <- function (name, name2=NULL, name3=NULL){

  #snipped code#

  cherrypickedpalette <- CustomPal(new_pal)

  #snipped code#

}

Function with Shiny

CustomPal <- function(new_pal){
  if (interactive()){
    #snipped code#
    }
    cherrypickedpalette <- runApp(list(
      #snipped code#
        mainPanel(
          h5('Your Cherry-Picked Palette',style = "font-weight: bold;"),
          fluidRow(column(12,verbatimTextOutput("col"))),
          actionButton("action", label = "I'm Done")
          )
      ),
      server = function(input,output,session){
        outputdata<-  reactive({
          input$col
        })

        output$col <- { 
          renderPrint(outputdata())
        }

        #Code to detect closing button
        observe({
          if (input$action > 0) 
            stopApp()
        })
        #Code to detect closing button

        session$onSessionEnded(function(){
          message <- paste(isolate(outputdata())," ")
          cat(message,file=colorfile, append=TRUE)
          cherrypickedpalette <<- scan(file=colorfile," ")
          stopApp(cherrypickedpalette)
          file.remove(colorfile)
        })
      }
    )
    )
  }
}
Artie Ladie
  • 521
  • 4
  • 14
  • There are still some mistakes in the code.. I think some parenthesis are too much at the end.. And why are you not using `observeEvent` for the `actionButton` ? And the ShinyApp is never called, it is stored inside a function, also the `interactive()` is never called? What about an `onStop(function(){})` instead of onSessionEnded? – SeGa Jun 10 '18 at 13:08
  • @SeGa With this code the Shiny app is called, user is able to select color palettes. Problem is once I introduced action button. Now, the color palettes are not getting stored in the global variable `cherrypickedpalette`, that's the issue. Will tinker witih code .... – Artie Ladie Jun 10 '18 at 15:08

1 Answers1

1

Using the github code, I am able to reproduce your app now. It seems that the onSessionEnded is called, as the file is written to disk and also the cat is called. So i dont think the problem is there. Somehow the cherrypickedpalette <<- is not assigning to the global environment.

But I dont understand why you have to write the results to disk and then scan them again to get the values? Is that for a specific reason?

I was able assigning the colors to the global environment using assign in the onSessionEnded function.

Try using this CustomPal function instead:

CustomPal <- function(new_pal){
  if (interactive()){
    cherrypickedpalette <- runApp(list(
      ui = {fluidPage(
        titlePanel("Cherry Pick Your Own Palette!"),
        sidebarPanel (hr(),
                      selectInput('col', 'Options', new_pal, multiple=TRUE, selectize=FALSE, size = 15)
        ),
        mainPanel(
          h5('Your Cherry-Picked Palette',style = "font-weight: bold;"),
          fluidRow(column(12,verbatimTextOutput("col"))),
          actionButton("action", label = "I'm Done")
        )
      )},
      server = function(input,output,session) {
        outputdata<-  reactive({
          input$col
        })
        output$col <- { 
          renderPrint(outputdata())
        }
        observeEvent(input$action, {
          stopApp()
        })

        session$onSessionEnded(function(){
          message <- paste(isolate(outputdata())," ")
          print(paste("Message: ", message))
          assign("cherrypickedpalette", message, pos =  .GlobalEnv)
          stopApp(cherrypickedpalette)
        })
      }
    )
    )
  }
}

After loading all functions, call the shinyApp, pick the colors, close the app by actionButton or closing the window and the colors should be stored in the variable cherrypickedpalette.

library(shiny)
CherryPickPalette("BiryaniRice","Kulfi","Haveli2")
cherrypickedpalette

UPDATE1:

You can also omit the whole onSessionEnded process and write the variable to global environment inside the observeEvent function.

Delete the session function and replace the observeEvent with this:

    observeEvent(input$action, {
      cherrypickedpalette <<- paste(isolate(outputdata())," ")
      stopApp()
    })

UPDATE2:

So the onSessionEnded works and the problem is actually with the scan function. It seems that you cannot write directly to the global environment with that function. But you can use it to store the value and in the next line assign this value to glob.env. With the following lines it should work too, if it is required to store values to disk.

      cherrypickedpalette <- scan(file=colorfile," ")
      cl <<- cherrypickedpalette
SeGa
  • 9,454
  • 3
  • 31
  • 70
  • Hello @SeGa. I thought that saving output from Shiny session required writing it out to disk, because it is isolated from rest of R. Your code looks much neater. Will try this out. – Artie Ladie Jun 10 '18 at 16:21
  • No, normally you can use `<<-` easily and also the assign `function` inside a shinyApp and it would work. Check out the [answers here](https://stackoverflow.com/questions/50650592/interactive-shiny-global-date-picker/50650746#50650746). Im not exactly sure why its not working in your case, but I didnt go trough the whole app, so maybe there is anther problem somewhere, or `<<-` does not work in `onSessionEnded`. – SeGa Jun 10 '18 at 16:25
  • Thank you, will check this. Saving to global variable is more streamlined than saving to file, reading from file and then deleting file. – Artie Ladie Jun 10 '18 at 16:32