Having some Issues with output of table in Shiny App.

Hello Guys,

I am new in Shiny app. As per my requirements, I have tried hard to work on codes to achieve the requirements. But, still, at some point, I am facing difficulties. I will be grateful to you if you could kindly help me out. Please find the codes at below, I apologize for messy codes.

My current difficulties are:
(1) I am able to see all the variables (of selected .csv file) in rhandsontable, but I am unable to select more than one variable at a time. I would like to select multiple variables at the same time and also one checkbox for all variable selection (like select all variables).

(2) I would like to add elementary statistical information of the selected column on the second page of dashboardBody.

I am looking forward to your positive response.

library(shiny)
library(shinydashboard)
library(rhandsontable)

ui = dashboardPage(
    dashboardHeader(title = "Assignment"),
    dashboardSidebar(
        sidebarMenu(
            menuItem("Laboratory", tabName = "Laboratory", icon = icon("dashboard"))
        )
    ),
    dashboardBody(
        fluidRow(
            selectInput(
                "select2", label = h3("Select Year"), selected = "lab2018.csv",
                choices = list("lab2016.csv", "lab2017.csv", "lab2018.csv")), 
            radioButtons("disp", "Display",
                         choices = c(All = "all",
                                     Tail = "tail"),
                         selected = "all"),
            uiOutput("checkbox")
            ),
        
        fluidRow(actionButton("saveBtn", "Save changes"),
                 downloadButton("downloadData", "Download", style = "position:absolute;right:0;")        
        ),
   
        fluidRow(
            box(rHandsontableOutput("hot"), width = 13, height = 408)
        )
    )
)
server <- function(input, output, session) {
    
    DF <- reactiveVal()
    observe({
        DF(read.csv(input$select2, stringsAsFactors = FALSE))
    })
    observe({
        if (!is.null(input$hot)) DF(hot_to_r(input$hot))
    })
    
    observeEvent(input$saveBtn, {
        if (!is.null(DF())) write.csv(DF(), input$select2, row.names = FALSE)
    })
    
    output$hot <- renderRHandsontable({
        rhandsontable(
        
        if(input$disp == "tail") {
            tail(df_sel())
        }
        else {
            df_sel()
            
        })
    })
    
     output$downloadData <- downloadHandler(
        filename = function(){
            paste(input$select2, input$filetype, sep = "")
        }, 
        content = function(file){
            write.csv(DF(), file)        
        }
    )
    
    output$checkbox <- renderUI({
        checkboxGroupInput(inputId = "select_var", 
                           label = "Select variables", 
                           choices = names(DF()), inline = TRUE)
    })
    
    output$hot <- renderRHandsontable({
        rhandsontable(df_sel(), width = "100%", height = 390) %>% 
            hot_table(highlightCol = TRUE, highlightRow = TRUE, readOnly = FALSE, selectCallback = TRUE) #%>%
            #hot_col("Status", readOnly = FALSE)     
    })
    
}

shinyApp(ui, server)

It's a bit hard to help you without some data. You can use dput() to give us a small amount of lab2018.csv data to run the app.

Also df_sel() is missing. I'm not sure what you are trying to achieve?

1 Like

You've also got output$hot defined twice. Also, you are modifying DF() in response to hot, which I think is unwise. Try this:

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

	DF <- reactiveVal()
	observe({
		DF(
			# read.csv(input$select2, stringsAsFactors = FALSE)
			mtcars # read some data
		)
	})
	df_sel <- reactiveVal()
	observe({
		req(length(input$select_var)>0) # avoid error when no variables selected
		df_sel(
			DF() %>%
				dplyr::select(one_of(input$select_var))
		)
	})
	# observe({ # don't change DF here
	# 	if (!is.null(input$hot)) DF(hot_to_r(input$hot))
	# })

	observeEvent(input$saveBtn, {
		if (!is.null(DF())) write.csv(DF(), input$select2, row.names = FALSE)
	})

	output$downloadData <- downloadHandler(
		filename = function(){
			paste(input$select2, input$filetype, sep = "")
		},
		content = function(file){
			write.csv(DF(), file)
		}
	)

	output$checkbox <- renderUI({
		req(DF()) # avoid error when DF() not defined yet
		checkboxGroupInput(inputId = "select_var",
						   label = "Select variables",
						   choices = names(DF()),
						   inline = TRUE)
	})

	output$hot <- renderRHandsontable({
		req(df_sel()) # avoid error when df_sel() not defined yet
		rhandsontable(df_sel(), width = "100%", height = 390) %>%
			hot_table(highlightCol = TRUE, highlightRow = TRUE, readOnly = FALSE, selectCallback = TRUE) #%>%
		#hot_col("Status", readOnly = FALSE)
	})

}
1 Like

Use downloadHandler again on df_sel() for your saveBtn.

To handle input$disp == "tail" put this in output$hot instead of df_sel()

if_else(input$disp == "tail", tail(df_sel()), df_sel()), ...
1 Like

Dear Woodward,

Thank you so much for your help. Kindly find some of the data sets as per requirements.

structure(list(Feed.TS = c(-1.785755627, -0.494567374, -0.649376292,
0.808157709, 0.609843677, 1.606608272, 0.774792836, 0.47423704,
0.015919365), Feed.VS = c(-0.724803449, -0.156711942, 0.461948492,
0.741159564, -2.907301012, -1.293504645, 1.275994464, 0.280900447,
1.07670672), Feed.COD = c(0.100835711, -1.241111092, 1.822960343,
-0.829869845, -0.982748257, 0.552525499, -0.767139224, 0.773854314,
2.003178546), Dosing.B = c("no", "no", "yes", "yes", "yes", "no",
"yes", "no", "no"), Dosing.C = c("yes", "no", "yes", "no", "no",
"no", "yes", "no", "no")), class = "data.frame", row.names = c(NA,
-9L))

Best regards,
A.

Dear Woodward,

As per your corrected codes, selections of variables working properly. But, I am facing some other issues. I will be grateful if you could help me to find out the solution to these issues.

Like:
(1) If I edit the table in the dashboard and save it, App couldn't remember the changes after re-run.
(2) If I edit the table in the dashboard and download it, it downloads raw file. I would like to download the edited version of the whole table.
(3) How can I create a checkbox for "select all" variables

I am looking forward to your reply. :slight_smile:

Best regards,
Ashish

Codes are:

library(shiny)
library(shinydashboard)
library(rhandsontable)
library(tidyverse)


ui = dashboardPage(
     dashboardHeader(title = "Assignment"),
    dashboardSidebar(
        sidebarMenu(
            menuItem("Laboratory", tabName = "Laboratory", icon = icon("dashboard"))
        )
    ),
    dashboardBody(
        fluidRow(
            selectInput(
                "select2", label = h3("Select Year"), selected = "lab2018.csv",
                choices = list("lab2016.csv", "lab2017.csv", "lab2018.csv")), 
            radioButtons("disp", "Display",
                         choices = c(All = "all",
                                     Tail = "tail"),
                         selected = "all", inline = TRUE),
            uiOutput("checkbox")
        ),
        
        fluidRow(actionButton("saveBtn", "Save changes"),
                 downloadButton("downloadData", "Download", style = "position:absolute;right:0;")         
        ),
        
        fluidRow(
            box(rHandsontableOutput("hot"), width = 13, height = 385)
        )
    )
    
)

server <- function(input, output, session) {
    
    DF <- reactiveVal()
    observe({
        DF(
            read.csv(input$select2, stringsAsFactors = FALSE)
        )
    })
    df_sel <- reactiveVal()
    observe({
        req(length(input$select_var)>0)  # avoid error when no variables selected
        df_sel(
            DF() %>%
                dplyr::select(one_of(input$select_var))
        )
    })
  
    observeEvent(input$saveBtn, {
        if (!is.null(DF())) write.csv(DF(), input$select2, row.names = FALSE)
    })
    
    output$downloadData <- downloadHandler(
        filename = function(){
            paste(input$select2, input$filetype, sep = "")
        },
        content = function(file){
            write.csv(DF(), file)
        }
    )
    
    output$checkbox <- renderUI({
        req(DF())  # avoid error when DF() not defined yet
        checkboxGroupInput(inputId = "select_var",
                           label = "Select variables",
                           choices = names(DF()),
                           inline = TRUE)
    })
    
    output$hot <- renderRHandsontable({
        req(df_sel()) # avoid error when df_sel() not defined yet
        rhandsontable(df_sel(), width = "100%", height = 390) %>%
            hot_table(highlightCol = TRUE, highlightRow = TRUE, readOnly = FALSE, selectCallback = TRUE) 
    })  
}

shinyApp(ui, server)

I used input$disp == "tail" function in output$hot. But, not able to open the table in the dashboard.
Basically, I am using because I want to see the last few rows of the table when I open the dashboard.

This fixes the "tail" problem. Regarding saving the table, you could try saveWidget. You can use updateCheckboxGroupInput to select options in select_var, see this link. Saving the state of the app between sessions is tricky, I just allow the user to save their inputs to a file, and load their inputs from a file.

	df_sel <- reactiveVal()
	observe({
		req(length(input$select_var)>0, input$disp)
		df_sel(
			DF() %>%
				dplyr::select(one_of(input$select_var)) %>%
				dplyr::slice(if_else(input$disp %in% "all", 1, n()-5):n())
		)
	})

1 Like

Thank you for your reply. Now I can select the variables from the list and also tail function works. But, I am concerning about download data. I can able to download a file (.csv) but it is raw file. I would like to download the edited data. I will be grateful if you could help me with that.

server codes are:

server <- function(input, output, session) {
    
    DF <- reactiveVal()
    observe({
        DF(
            read.csv(input$select2, stringsAsFactors = FALSE)
        )
    })
    
    df_sel <- reactiveVal()
    observe({
        req(length(input$select_var)>0, input$disp)
        df_sel(
            DF() %>%
                dplyr::select(one_of(input$select_var)) %>%
                dplyr::slice(if_else(input$disp %in% "all", 1, n()-5):n())
        )
    })
    
    observeEvent(input$saveBtn, {
        if (!is.null(df_sel())) write.csv(DF(), input$select2, row.names = FALSE)
    })
    
    output$downloadData <- downloadHandler(
        filename = function(){
            paste(Sys.Date(), "_", input$select2, ".csv", sep = "")  
        },
        content = function(file){
            write.csv(DF(), file)
        }
    )
  
    output$selection <- renderUI({
        inFile <- input$select2
        
        if (is.null(inFile))
            return(NULL)
        
            pickerInput(
                inputId = "select_var", 
                label = "Select/deselect Variables", 
                choices = names(DF()), 
                options = list(
                    `actions-box` = TRUE, 
                    size = 10,
                    `selected-text-format` = "count > 3"
                ), 
                multiple = TRUE
            )
    })
    
    output$hot <- renderRHandsontable({
        req(df_sel()) # avoid error when df_sel() not defined yet
        rhandsontable(df_sel(), width = "100%", height = 390) %>%
            hot_table(highlightCol = TRUE, highlightRow = TRUE, readOnly = FALSE, selectCallback = TRUE) #%>%
        #hot_col("Status", readOnly = FALSE)
    })