reactive value resets to NA when new row inserted rhandsontable shiny - r

I have a Shiny app with a rhandsontable and an infobox which reports the remaining budget, based on an initial budget (1000) and the values users put in the rhandsontable.
The value of the remaining budget updates correctly based on the value of the W column, however, when inserting a new row the value first changes to NA, before it gets recomputed, based on the value entered.
I would like to value of the Remaining Budget infobox to stay the same until the new values are added. Below my code:
library(shiny)
library(rhandsontable)
library(dplyr)
library(shinydashboard)
ui <- fluidPage( fluidRow(column(6, uiOutput("selA"))),
fluidRow(column(6, rHandsontableOutput('tbl1'))),
fluidRow(column(6,box(title = "Remaining budget", width = 6, status = "info",
textOutput("infoRestBudget"))))
)
server <- function(input, output, session){
dt0 <- data.frame( A = c("S2","S2","S2","S4","S4","S4"),
B = c("1","2","3","1","2","3"),
C = c(10,20,30,40,15,25),
D = c("A","B","C","D","E","F"))
# get the data for the selected BA
dt <- reactive(subset(dt0, A %in% input$selA))
# Render selectInput selBA
output$selA <- renderUI({
ba <- as.vector( unique(dt0$A) )
selectInput("selA","Choose BA", choices = ba)
})
DF <- data.frame("X" = c(""),
"Y" = c(""),
"Z" = c(""),
"Type_action" = c(""),
"W" = NA_integer_)
values <- reactiveValues(data = DF)
Y <- reactiveVal()
Z <- reactiveVal()
observe({
if(!is.null(input$tbl1)){
values$data <- as.data.frame(hot_to_r(req(input$tbl1)))
}
})
observeEvent(input$tbl1,{
Y(hot_to_r(input$tbl1)$Y)},
ignoreInit= TRUE
)
observeEvent(input$tbl1,{
Z(hot_to_r(input$tbl1)$Z)},
ignoreInit= TRUE
)
output$tbl1 = renderRHandsontable({
req(input$selA)
tmpTable <- rhandsontable(values$data, rowHeaders = FALSE, selectCallback = TRUE, width =
1000, height = 200) %>%
hot_table(highlightCol = TRUE, highlightRow = TRUE, stretchH = "all") %>%
hot_col(col = "X", type = "dropdown", colWidths = 90, source =
sort(unique(dt()$B))) %>%
hot_col(col = "Y", type = "dropdown", colWidths = 65, source =
sort(unique(dt()$D))) %>%
hot_col(col = "Z", type = "dropdown", colWidths = 60,source =
sort(unique(dt()$D))) %>%
hot_col(col = "Type_action", colWidths = 50, readOnly = TRUE, type = "text") %>%
hot_col(col = "W", colWidths = 50, readOnly = TRUE, type = "numeric")
if(!is.null(input$tbl1_select$select$r) && !is.na(values$data$Y[input$tbl1_select$select$r])
&& !is.na(values$data$Z[input$tbl1_select$select$r])){
values$data$Type_action <- ifelse(match(Y(), LETTERS) < match(Z(), LETTERS),"Upgrade","Downgrade")
if(!is.null(input$tbl1_select$select$r) && !is.na(values$data$Y[input$tbl1_select$select$r])
&& !is.na(values$data$Z[input$tbl1_select$select$r])){
val <- 100
values$data$W <- ifelse((match(Y(), LETTERS) < match(Z(), LETTERS)), val, -val)
}
}
tmpTable
})
val_W <- reactiveVal()
observeEvent(input$tbl1,{
val_W(hot_to_r(input$tbl1)$W)},
ignoreInit= TRUE
)
budget <- 1000
restBudget <- reactiveValues(val = budget)
observeEvent(input$tbl1, {
if(is.null(input$tbl1)){
restBudget$val <- budget} else{
restBudget$val <- budget - sum(as.numeric(val_W()))
}
}, ignoreInit = TRUE)
output$infoRestBudget <- renderText({
req(input$tbl1)
euro <- "\u20AC"
res <- paste(euro, "", restBudget$val)
res
})
}
shinyApp(ui, server)

Try the code below. You are getting NA because the new rows appear with no data in them. When there is an NA in X, Y, or Z "Remaining Budget" is NA because it needs non-NA values to be calculated. When you add a new row you introduce NAs to the calculation so it becomes NA.
The solution is to set default values for your new rows. In the hot_col(...) objects you can set a default value for columns in new rows.
I have set X = 1, Y = A, Z = A but use whatever you think is best for your application.
library(shiny)
library(rhandsontable)
library(dplyr)
library(shinydashboard)
ui <- fluidPage( fluidRow(column(6, uiOutput("selA"))),
fluidRow(column(6, rHandsontableOutput('tbl1'))),
fluidRow(column(6,box(title = "Remaining budget", width = 6, status = "info",
textOutput("infoRestBudget"))))
)
server <- function(input, output, session){
dt0 <- data.frame( A = c("S2","S2","S2","S4","S4","S4"),
B = c("1","2","3","1","2","3"),
C = c(10,20,30,40,15,25),
D = c("A","B","C","D","E","F"))
# get the data for the selected BA
dt <- reactive(subset(dt0, A %in% input$selA))
# Render selectInput selBA
output$selA <- renderUI({
ba <- as.vector( unique(dt0$A) )
selectInput("selA","Choose BA", choices = ba)
})
DF <- data.frame("X" = c(""),
"Y" = c(""),
"Z" = c(""),
"Type_action" = c(""),
"W" = NA_integer_)
values <- reactiveValues(data = DF)
Y <- reactiveVal()
Z <- reactiveVal()
observe({
if(!is.null(input$tbl1)){
values$data <- as.data.frame(hot_to_r(req(input$tbl1)))
}
})
observeEvent(input$tbl1,{
Y(hot_to_r(input$tbl1)$Y)},
ignoreInit= TRUE
)
observeEvent(input$tbl1,{
Z(hot_to_r(input$tbl1)$Z)},
ignoreInit= TRUE
)
output$tbl1 = renderRHandsontable({
req(input$selA)
tmpTable <- rhandsontable(values$data, rowHeaders = FALSE, selectCallback = TRUE, width =
1000, height = 200) %>%
hot_table(highlightCol = TRUE, highlightRow = TRUE, stretchH = "all") %>%
hot_col(col = "X", type = "dropdown", colWidths = 90, default = "1" , source =
sort(unique(dt()$B))) %>%
hot_col(col = "Y", type = "dropdown", colWidths = 65, default = "A", source =
sort(unique(dt()$D))) %>%
hot_col(col = "Z", type = "dropdown", colWidths = 60, default = "A", source =
sort(unique(dt()$D))) %>%
hot_col(col = "Type_action", colWidths = 50, readOnly = TRUE, type = "text") %>%
hot_col(col = "W", colWidths = 50, readOnly = TRUE, type = "numeric")
if(!is.null(input$tbl1_select$select$r) && !is.na(values$data$Y[input$tbl1_select$select$r])
&& !is.na(values$data$Z[input$tbl1_select$select$r])){
values$data$Type_action <- ifelse(match(Y(), LETTERS) < match(Z(), LETTERS),"Upgrade","Downgrade")
if(!is.null(input$tbl1_select$select$r) && !is.na(values$data$Y[input$tbl1_select$select$r])
&& !is.na(values$data$Z[input$tbl1_select$select$r])){
val <- 100
values$data$W <- ifelse((match(Y(), LETTERS) < match(Z(), LETTERS)), val, -val)
}
}
tmpTable
})
val_W <- reactiveVal()
observeEvent(input$tbl1,{
val_W(hot_to_r(input$tbl1)$W)},
ignoreInit= TRUE
)
budget <- 1000
restBudget <- reactiveValues(val = budget)
observeEvent(input$tbl1, {
if(is.null(input$tbl1)){
restBudget$val <- budget} else{
restBudget$val <- budget - sum(as.numeric(val_W()))
}
}, ignoreInit = TRUE)
output$infoRestBudget <- renderText({
req(input$tbl1)
euro <- "\u20AC"
res <- paste(euro, "", restBudget$val)
res
})
}
shinyApp(ui, server)

Related

How to add columns to table rendered with rhandsontable with dropdown menus using an action button?

I'm working on a table rendered with rhandsontable that uses dropdown menus for user inputs into the table. My dropdown approach is based on guidance provided in post Is there a way to have different dropdown options for different rows in an rhandsontable?. I'm trying to add a feature where the user clicks on an actionButton() in order to add a column to the table and sequentially numbers the header for the added column, with the dropdowns included in the added column. The below code almost works, except that added columns don't have the required dropdowns. What am I doing wrong here?
Code:
library(shiny)
library(rhandsontable)
ui <- fluidPage(br(),
mainPanel(
actionButton("add", "Add column"),br(),br(),
rHandsontableOutput("Tbl")
)
)
server <- function(input, output) {
DF <- reactiveVal(
data.frame(
'Series 1' = NA_character_,
stringsAsFactors = FALSE,
row.names = c("Select option"),
check.names = FALSE
)
)
observeEvent(input$Tbl,{DF(hot_to_r(input$Tbl))})
output$Tbl <- renderRHandsontable({
select_option <- c(NA_character_, "dog", "cat") # defines the dropdown options
tmp <- rhandsontable(DF(), rowHeaderWidth = 200, selectCallback = TRUE, height = 300) %>%
hot_cols(colWidths = 100) %>%
hot_col("Series 1",
allowInvalid = FALSE,
type = "dropdown",
source = NA_character_,
readOnly = TRUE
)
tmp <- hot_col(tmp,
col = "Series 1",
allowInvalid = FALSE,
type = "dropdown",
source = select_option
) %>%
hot_cell(row = input$Tbl_select$select$r, col = "Series 1", readOnly = FALSE)
tmp
})
observeEvent(input$add, {
select_option <- c(NA_character_, "dog", "cat") # defines the dropdown options
newCol <- data.frame('Series 1' = NA_character_,stringsAsFactors = FALSE)
names(newCol) <- paste("Series", ncol(hot_to_r(input$Tbl)) + 1)
DF(cbind(DF(), newCol))
})
}
shinyApp(ui = ui, server = server)
You need to apply hot_col(type = "dropdown") on every column of the reactive data.frame (col = names(DF())) not only on the first col = "Series 1":
library(shiny)
library(rhandsontable)
ui <- fluidPage(br(),
mainPanel(
actionButton("add", "Add column"),br(),br(),
rHandsontableOutput("Tbl")
)
)
server <- function(input, output) {
DF <- reactiveVal(
data.frame(
'Series 1' = NA_character_,
stringsAsFactors = FALSE,
row.names = c("Select option"),
check.names = FALSE
)
)
observeEvent(input$Tbl,{DF(hot_to_r(input$Tbl))})
output$Tbl <- renderRHandsontable({
select_option <- c(NA_character_, "dog", "cat") # defines the dropdown options
rhandsontable(DF(), rowHeaderWidth = 200, selectCallback = TRUE, height = 300) %>%
hot_cols(colWidths = 100) %>%
hot_col(col = names(DF()),
allowInvalid = FALSE,
type = "dropdown",
source = select_option
) %>%
hot_cell(row = input$Tbl_select$select$r, col = "Series 1", readOnly = FALSE)
})
observeEvent(input$add, {
select_option <- c(NA_character_, "dog", "cat") # defines the dropdown options
newCol <- data.frame('Series 1' = NA_character_,stringsAsFactors = FALSE)
names(newCol) <- paste("Series", ncol(hot_to_r(input$Tbl)) + 1)
DF(cbind(DF(), newCol))
})
}
shinyApp(ui = ui, server = server)
Following up on ismirsehregal's solution for column addition, the below offers both column addition and deletion via actionButton():
library(shiny)
library(rhandsontable)
ui <- fluidPage(br(),
mainPanel(
actionButton("add", "Add column"),br(),br(),
actionButton("delSeries","Select series below to delete"),
uiOutput("delSeries2"),
rHandsontableOutput("Tbl")
)
)
server <- function(input, output) {
DF <- reactiveVal(
data.frame(
'Series 1' = NA_character_,
stringsAsFactors = FALSE,
row.names = c("Select option"),
check.names = FALSE
)
)
observeEvent(input$Tbl,{DF(hot_to_r(input$Tbl))})
output$Tbl <- renderRHandsontable({
select_option <- c(NA_character_, "dog", "cat") # defines the dropdown options
tmp <- rhandsontable(DF(), rowHeaderWidth = 200, selectCallback = TRUE, height = 300) %>%
hot_cols(colWidths = 100) %>%
hot_col("Series 1",
allowInvalid = FALSE,
type = "dropdown",
source = NA_character_,
readOnly = TRUE
)
tmp <- hot_col(tmp,
col = names(DF()), # adding this is what fixed it
allowInvalid = FALSE,
type = "dropdown",
source = select_option
) %>%
hot_cell(row = input$Tbl_select$select$r, col = "Series 1", readOnly = FALSE)
tmp
})
observeEvent(input$add, {
newCol <- data.frame('Series 1' = NA_character_,stringsAsFactors = FALSE)
names(newCol) <- paste("Series", ncol(hot_to_r(input$Tbl)) + 1)
DF(cbind(DF(), newCol))
})
observeEvent(input$delSeries3, {
tmp <- DF()
delCol <- input$delSeries3
tmp <- tmp[ , !(names(tmp) %in% delCol), drop = FALSE]
newNames <- sprintf("Series %d",seq(1:ncol(tmp)))
names(tmp) <- newNames
DF(tmp)
})
output$delSeries2 <-
renderUI(
selectInput("delSeries3",
label = NULL,
choices = colnames(hot_to_r(input$Tbl)),
selected = "",
multiple = TRUE,
width = '110px')
)
}
shinyApp(ui = ui, server = server)

Empty Date fields in data table generate error in shiny app

I have the following shiny app where the user can change the values of a table, however, if the user leaves an empty date field it generates an error but I don't know how to solve it.
I have tried to put the new value as as.character, as.Date, as.Posixct but it has not worked, I would appreciate any kind of guidance or help.
This is the message that the console throws:
Warning: Error in charToDate: character string is not in a standard unambiguous format
[No stack trace available]
Thank you
library(shiny)
#library(shinyjs)
library(DT)
#library(data.table)
#library(shinyalert)
#library(openxlsx)
#library(shinyFiles)
#library(dplyr)
#library(stringi)
#useShinyalert()
df <- data.frame(
Var1 = letters[1:10],
Var2 = round(rnorm(10),3),
Date1 = seq(as.Date("2000/01/01"), by = "month", length.out = 10),
Date2 = seq(as.Date("2000/01/01"), by = "month", length.out = 10)
)
d1 <- reactiveValues()
d1$Data <- df
server <- function(input, output, session){
# RENDER TABLE ----
data.tabla <- reactive({
df <- d1$Data
return(df)
})
output$df_data <- renderDataTable({
df <- datatable(
data.tabla(),
selection = 'single', editable = TRUE, rownames = FALSE,
options = list(
paging = TRUE,
# scrollX = TRUE,
searching = TRUE,
fixedColumns = TRUE,
autoWidth = TRUE,
ordering= FALSE,
dom = 'Bfrtip',
buttons = c('excel')
),
class = "display"
)
return(df)
})
observeEvent(input$df_data_cell_edit, {
d1$Data[input$df_data_cell_edit$row,
input$df_data_cell_edit$col+1] <<- input$df_data_cell_edit$value
})
}
# UI ----
ui <- fluidPage(
sidebarPanel(),
mainPanel(
DT::dataTableOutput("df_data"))
)
shinyApp(ui, server)
You should not use the global assignment operator <<- along with reactiveValues. Please try the following:
library(shiny)
library(DT)
DF <- data.frame(
Var1 = letters[1:10],
Var2 = round(rnorm(10), 3),
Date1 = seq(as.Date("2000/01/01"), by = "month", length.out = 10),
Date2 = seq(as.Date("2000/01/01"), by = "month", length.out = 10)
)
d1 <- reactiveValues(Data = DF)
server <- function(input, output, session) {
DT <- reactive({
d1$Data
})
output$df_data <- renderDataTable({
datatable(
DT(),
selection = 'single',
editable = TRUE,
rownames = FALSE,
options = list(
paging = TRUE,
# scrollX = TRUE,
searching = TRUE,
fixedColumns = TRUE,
autoWidth = TRUE,
ordering = FALSE,
dom = 'Bfrtip',
buttons = c('excel')
),
class = "display"
)
})
observeEvent(input$df_data_cell_edit, {
d1$Data[input$df_data_cell_edit$row, input$df_data_cell_edit$col + 1] <- input$df_data_cell_edit$value
})
}
ui <- fluidPage(sidebarPanel(), mainPanel(DT::dataTableOutput("df_data")))
shinyApp(ui, server)
You could check that the Date columns are in proper Date format:
library(shiny)
df <- data.frame(
Var1 = letters[1:10],
Var2 = round(rnorm(10),3),
Date1 = seq(as.Date("2000/01/01"), by = "month", length.out = 10),
Date2 = seq(as.Date("2000/01/01"), by = "month", length.out = 10)
)
d1 <- reactiveValues()
d1$Data <- df
server <- function(input, output, session){
# RENDER TABLE ----
data.tabla <- reactive({
df <- d1$Data
return(df)
})
output$df_data <- renderDataTable({
df <- datatable(
data.tabla(),
selection = 'single', editable = TRUE, rownames = FALSE,
options = list(
paging = TRUE,
# scrollX = TRUE,
searching = TRUE,
fixedColumns = TRUE,
autoWidth = TRUE,
ordering= FALSE,
dom = 'Bfrtip',
buttons = c('excel')
),
class = "display"
)
return(df)
})
observeEvent(input$df_data_cell_edit, {
value <- input$df_data_cell_edit$value
row <- input$df_data_cell_edit$row
col <- input$df_data_cell_edit$col + 1
if (col >= 3 & tryCatch({
as.Date(value); TRUE},error = function(err) {FALSE}) ) {
d1$Data[row,col] <<- input$df_data_cell_edit$value
} else {
showModal(modalDialog(
title = "Wrong date format",
"Check date format!"
))
d1$Data[row,col] <- NA
}
})
}
# UI ----
ui <- fluidPage(
sidebarPanel(),
mainPanel(
DT::dataTableOutput("df_data"))
)
shinyApp(ui, server)

checkboxInput value R shiny: if TRUE then

I have the following code. The objective is to make the position of the plot bars reactive to the selectInput value
library(shiny)
library(shinyWidgets)
library(tidyverse)
library(DT)
library(shinythemes)
library(plotly)
library(ggthemes)
library(lubridate)
data <- data.frame(mitarbeiter = c("AA", "BB", "CC", "DD", "EE", "FF"),
art = c("hr", "GG", "TT", "RR", "OO", "OO"),
creadate = as_date(c("2018-01-03", "2018-01-03", "2018-01-03", "2018-01-03", "2018-01-03", "2018-01-03")))
mitarbeiter1 <- sort(unique(data$mitarbeiter))
art1 <- sort(unique(data$art))
year_month <- function(dates) {
paste(lubridate::year(dates),
str_pad(lubridate::month(dates), width = 2, pad = 0),
sep="-")
}
year_week <- function(dates) {
paste(lubridate::year(dates),
str_pad(lubridate::week(dates), width = 2, pad = 0),
sep="-")
}
year_day <- function(dates) {
paste(lubridate::year(dates),
str_pad(lubridate::month(dates), width = 2, pad = 0),
str_pad(lubridate::day(dates), width = 2, pad = 0),
sep="-")
}
ui <- fluidPage(
fluidRow(
column(4,
pickerInput("mitarbeiterName", "Name des Mitarbeiters", mitarbeiter1,
options = list(`actions-box` = TRUE), multiple = TRUE),
pickerInput("artName", "Art", art1,
options = list(`actions-box` = TRUE), multiple = TRUE),
pickerInput("period", "Zeitraum", c("day", "week", "month", "year"),
options = list(`actions-box` = TRUE)),
dateRangeInput("date", "Datum auswahlen", start = "2020-01-01"),
checkboxInput("kumulativ", "Kumulativ"),
downloadButton("download", "Download")
),
column(8,
plotlyOutput("policyPlot")
)
)
)
server <- function(input, output, session) {
#create a reactive object with a NULL starting value
listofrows <- reactiveValues(data = NULL)
#observe the changes in inputs and update the reactive object
observeEvent(c(input$mitarbeiterName, input$artName, input$date, input$period), {
req(input$mitarbeiterName)
req(input$artName)
req(input$period)
req(input$date)
listofrows$data <- subset(data, mitarbeiter %in% input$mitarbeiterName &
art %in% input$artName &
creadate >= input$date[1] & creadate <= input$date[2])
}, ignoreInit = T, ignoreNULL = TRUE)
output$policyPlot <- renderPlotly({
req(listofrows$data)
req(input$kumulativ)
fn <- switch(
input$period,
day = year_day,
week = year_week,
month = year_month,
year = year
)
pos <- if (input$kumulativ) "dodge" else "identity"
ggplot(listofrows$data) +
geom_bar(aes(x = fn(creadate), fill = mitarbeiter),
stat = "count",
position = pos,
show.legend = T) +
ggtitle("Anzahl erstellte Policen (pro Mitarbeiter)") +
xlab("Zeitraum") + ylab("Anzahl der Policen")
})
output$download <- downloadHandler(
filename = function() {
paste("data-", Sys.Date(), ".png", sep = "")
},
content = function(file) {
ggsave(file, plot = output$policyPlot)
})
}
shinyApp(ui, server)
Now, I want:
the position to be "dodge" if checkboxInput = TRUE, and
the position to be "identity" if checkboxInput = FALSE.
does someone have any suggestion how to do that? How can we do the if condition with the checkbox value?
In your case, req(input$kumulativ) doesn't work. It's because req checks if a value is "truthy", and FALSE is not considered truthy. Therefore, you can change it to:
req(!is.null(input$kumulativ))

Select max 2 different groups with pickerInput

I would like to restrict a pickerInput from shinyWidgets so that only elements from a maximum of 2 different groups can be selected. I know that I can restrict the selection to max 2 elements or to 2 elements per group, but I did not find a way to have max 2 groups selected, no matter the amount of selected elements inside those groups.
Here is a little toy example:
library(shiny)
library(shinyWidgets)
ui <- fluidPage(
pickerInput("groupslct", "Select elements from max 2 diff. Groups:",
choices = list(
Group1 = c(opt1 = "g11",
opt2 = "g12",
opt3 = "g13"),
Group2 = c(opt1 = "g21"),
Group3 = c(opt1 = "g31"),
Group4 = c(opt1 = "g41",
opt2 = "g42",
opt3 = "g43")
),
selected = 1, multiple = TRUE,
options = list("liveSearch" = TRUE,
# "max-options" = 2,
"max-options-group" = 2,
"selectOnTab" = TRUE
))
)
server <- function(input, output, session) {
observe({
print(input$kennwertauswahl)
})
}
shinyApp(ui, server)
I found a way using shinyjs, because updatePickerInput doesn't immediately refresh the input when changing the selected options.
library(shiny)
library(shinyjs)
library(shinyWidgets)
kennwertmap <- data.frame(vals=c("v", "vfree", "vref", "t", "state", "index", "index1", "index2"),
grp=c("v","v","v",
"t","s",
"ix","ix","ix"), stringsAsFactors = FALSE)
ui <- fluidPage(
useShinyjs(),
splitLayout(cellWidths = c("30%", "70%"),
div(style = "height: 1000px;",
pickerInput(("kennwertauswahl"), "Auswahl",
choices = list(
v = c(`mean v` = "v",
`mean v free` = "vfree",
`mean v ref` = "vref"),
t = c(`time` = "t"),
s = c(state = "state"),
i = c(index = "index",
index1 = "index1",
index2 = "index2")
),
selected = 1, multiple = TRUE,
options = pickerOptions(liveSearch = TRUE,
selectOnTab = TRUE))
),
div(
verbatimTextOutput("txt"),
verbatimTextOutput("txt1")
)
)
)
server <- function(input, output, session) {
kennwert <- reactiveValues(a = NULL)
observe({
if (is.null(input$kennwertauswahl)) {
kennwert$a <- NULL
} else {
isolate({
knwn <- input$kennwertauswahl
mappedkenw <- kennwertmap[kennwertmap$vals %in% knwn, ]
if (is.null(kennwert$a)) {
kennwert$a <- mappedkenw
} else {
## Check if 2 Groups already selected
if (length(unique(mappedkenw$grp)) > 2) {
## Grp to Remove
firstgrp <- kennwert$a[kennwert$a$grp != unique(kennwert$a$grp)[2],]
## Add One if new
newone <- setdiff(mappedkenw[,"vals"], kennwert$a$vals)
newone <- kennwertmap[kennwertmap$vals %in% newone, ]
newgrp <- rbind(firstgrp, newone)
kennwert$a <- newgrp
updatePickerInput(session, "kennwertauswahl", selected = newgrp$vals)
delay(100, runjs(HTML('$("#kennwertauswahl").selectpicker("refresh")')))
} else {
## Add One if new
newone <- setdiff(mappedkenw[,"vals"], kennwert$a$vals)
if (length(newone) != 0) {
newone <- kennwertmap[kennwertmap$vals %in% newone, ]
kennwert$a <- rbind(kennwert$a, newone)
}
## Remove One
lessone <- setdiff(kennwert$a$vals, mappedkenw[,"vals"])
if (length(lessone) != 0) {
kennwert$a <- kennwert$a[kennwert$a$vals != lessone,]
}
}
}
})
}
})
output$txt <- renderPrint({
print(input$kennwertauswahl)
})
output$txt1 <- renderPrint({
print(kennwert$a)
})
}
shinyApp(ui, server)

Rendering a shiny datatable with a caption/title and pre-selected rows

I'm trying to code a shiny app for plotting xy data. Each xy point is associated with several factors:
set.seed(1)
data.df <- data.frame(x = rnorm(1000), y = rnorm(1000),
sex = sample(c("F", "M"), 1000, replace = T),
age = sample(c("Y", "O"), 1000, replace = T),
group = sample(c("A", "B", "C", "D"), 1000, replace = T),
stringsAsFactors = F)
design.df <- data.frame(factor.name = c(c(rep("sex",2), rep("age",2), rep("group",4))),
factor.levels = c("F", "M","Y", "O","A", "B", "C", "D"), stringsAsFactors = F)
I would like to enable the user to subset the xy data (data.df) based on a selection of multiple rows from design.df using DT::renderDT within renderUI in the server, where the default selection is all rows of design.df. This works fine using this code:
suppressPackageStartupMessages(library(dplyr))
suppressPackageStartupMessages(library(shiny))
suppressPackageStartupMessages(library(DT))
server <- function(input, output)
{
output$design.idx <- renderUI({
output$design.df <- DT::renderDT(design.df, server = TRUE, selection = list(mode = "multiple", selected = rownames(design.df)[1:nrow(design.df)]))
DT::dataTableOutput("design.df")
})
xy.plot <- reactive({
if(!is.null(input$design.df_rows_selected)){
selected.design.df <- design.df[input$design.df_rows_selected,,drop = FALSE]
selected.idx <- lapply(unique(selected.design.df$factor.name), function(f) which(data.df[,f] %in% dplyr::filter(selected.design.df, factor.name == f)$factor.levels)) %>%
unlist() %>% unique()
plot.df <- data.df[selected.idx,,drop=F]
xy.plot <- suppressWarnings(plotly::plot_ly(marker = list(size = 3), type = 'scatter', mode = "markers", x = plot.df$x, y = plot.df$y, showlegend = FALSE) %>%
plotly::layout(xaxis = list(zeroline = FALSE, showticklabels = FALSE, showgrid = FALSE), yaxis = list(zeroline = FALSE, showticklabels = FALSE, showgrid = FALSE)))
} else{
xy.plot <- NULL
}
return(xy.plot)
})
output$outPlot <- plotly::renderPlotly({
xy.plot()
})
}
ui <- fluidPage(
titlePanel("Results Explorer"),
sidebarLayout(
sidebarPanel(
uiOutput("design.idx")
),
mainPanel(
plotly::plotlyOutput("outPlot")
)
)
)
shinyApp(ui = ui, server = server)
But I would also like to have a title or caption for the rendered datatable, so I tried replacing:
output$design.df <- DT::renderDT(design.df, server = TRUE, selection = list(mode = "multiple", selected = rownames(design.df)[1:nrow(design.df)]))
with:
output$design.df <- DT::renderDT(datatable(design.df, caption = "Subset Selection"), server = TRUE, selection = list(mode = "multiple", selected = rownames(design.df)[1:nrow(design.df)]))
in which case the selected = rownames(design.df)[1:nrow(design.df)] argument seems to be ignored and the default selection is no rows.
Changing selected = rownames(design.df)[1:nrow(design.df)] to selected = 1:nrow(design.df) makes no difference.
Any idea how to get both a title or caption to the rendered table together with have all rows as a pre-selection default?
You have to put selection in the datatable object:
output$design.df <- DT::renderDT(
datatable(design.df,
caption = "Subset Selection",
selection = list(mode = "multiple",
selected = rownames(design.df)[1:nrow(design.df)])
),
server = TRUE)

Resources