user3245256
user3245256

Reputation: 1948

Continuous updating of conditional values in a rhandsontable

I have a mini Shiny app that is working as desired. First, in the app's folder I generate a list with data frames for two stores:

stores <- list(store1 = tibble(Date = as.Date(c("2019-08-31", "2019-09-01", NA)), Item = c("A", "B", NA),
                              Price = c(100, 120, NA), Comment = as.character(rep(NA, 3))),
               store2 = tibble(Date = as.Date(c("2019-08-31", NA, NA)), Item = c("C", NA, NA),
                              Price = c(95, NA, NA), Comment = as.character(rep(NA, 3))))
saveRDS(stores, file = "stores.rds")
print(stores)

And here is my Shiny code. I want the user to be able to update information in each store's table as desired and save the changes by clicking on "Update store info" action button.

However, notice: at the end of the server code I have this 'conditional' line: mutate(Comment = ifelse(Price > 100, "Nice!", Comment)): If Price is > 100, a comment "Nice!" should appear - without my having to enter it manually.

Question: I don't know how to make this conditional comment appear in the table on the screen right upon clicking on input$update_store. I can switch to another store in the pull-down and come back to the first store - and the comment will be there! But is there a way to make it update immediately after input$update_store is clicked?

Thank you very much for your help!

library(shiny)
library(dplyr)
library(rhandsontable)
# Read in the existing list of stores:
stores <- readRDS("stores.rds")
print("Reading in stores the first time:")
print(stores)

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
### ui code ####
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ui <- fluidPage(

    titlePanel("My UI"), # Application title
    sidebarLayout(       # Sidebar with a pull-down to select a store:
        sidebarPanel(
            selectizeInput("store_select", label = "Select store",
                           choices = names(stores), multiple = FALSE,
                           selected = names(stores)[1]),
            actionButton("update_store", "Update store Info")
        ),

        mainPanel(       # Main panel with an editable table:
            rHandsontableOutput("store_table")
        )
    )
)

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

    stores_reactive <- reactiveValues( # Creating reactive values for stores:
        stores = stores
    )

    # What happens when one store is selected:
    mystore <- eventReactive(input$store_select, {
        store_name <- input$store_select
        store_table <- stores_reactive$stores[[store_name]]
        return(store_table)
    })
    # rhandsontable to be shown:
    output$store_table <- renderRHandsontable({
        rhandsontable(mystore())
    })

    # What happens upon pressing button "Update store Info":
    observeEvent(input$update_store, {
        stores[[input$store_select]] <- hot_to_r(input$store_table) %>% 
            mutate(Comment = ifelse(Price > 100, "Nice!", Comment))
        stores_reactive$stores <- stores      # Update stores_reactive
        saveRDS(stores, file = "stores.rds")  # save stores to the file
        stores <<- stores                     # Update 'stores' list
    })
}

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
### Run the app #### 
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
shinyApp(ui = ui, server = server)

Upvotes: 1

Views: 58

Answers (1)

Ben
Ben

Reputation: 30474

You do not need mystore to be an eventReactive method for input$store_select. If the action button is clicked (input$update_store) your mystore method will not be called, since store_select did not change.

If you want to keep the mystore function, you can do the following and it should work.

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

  stores_reactive <- reactiveValues( # Creating reactive values for stores:
    stores = stores
  )

  # What happens when one store is selected:
  mystore <- function(store_name) {
    store_table <- stores_reactive$stores[[store_name]]
    return(store_table)
  }

  output$store_table <- renderRHandsontable({
    rhandsontable(mystore(input$store_select))
  })

  # What happens upon pressing button "Update store Info":
  observeEvent(input$update_store, {
    stores[[input$store_select]] <- hot_to_r(input$store_table) %>% 
      mutate(Comment = ifelse(Price > 100, "Nice!", Comment))
    stores_reactive$stores <- stores      # Update stores_reactive
    saveRDS(stores, file = "stores.rds")  # save stores to the file
    stores <<- stores                     # Update 'stores' list
  })
}

Or you can do without the mystore function completely with the following:

# rhandsontable to be shown:
output$store_table <- renderRHandsontable({
  rhandsontable(stores_reactive$stores[[input$store_select]])
})

Upvotes: 1

Related Questions