I'm writing an online table by Shiny of R language, but something confusing stops me.
What I need is:
Show the full table for the first time.
If you type a number in the input block and submit, just show the top n rows of the table automatically.
What I see is:
DFflt, the variable behind the table, is already changed after submission, but the table on the webpage cannot be reloaded before you refresh the page manually.
What can I do to solve this problem? Thanks!
library(shiny)
library(tidyverse)
DF <- mpg
DFflt <- mpg
ui <- fluidPage(
numericInput("nrow", "Slice the top n rows of DF", value = 0),
actionButton("submit", "Submit"),
actionButton("p_DFflt", "print DFflt in console"),
div('render DFflt:'),
tableOutput("table")
)
server <- function(input, output, session) {
observeEvent(input$submit, {
nrow <- input$nrow
if (nrow > 10) {
showNotification(str_c("Invalid", type="error")) }
else { DFflt <<- DF %>% head(nrow) }
})
observeEvent(input$p_DFflt, { print(DFflt)} )
output$table <- renderTable({DFflt})
}
shinyApp(ui, server)
This should work as you expected:
library(shiny)
library(tidyverse)
DF <- mpg
ui <- fluidPage(
numericInput("nrow", "Slice the top n rows of DF", value = 0),
actionButton("submit", "Submit"),
actionButton("p_DFflt", "print DFflt in console"),
div('render DFflt:'),
tableOutput("table")
)
server <- function(input, output, session) {
n_row <- eventReactive(input$submit, {
input$nrow
})
observe({
if (n_row() > 10) {
showNotification(str_c("Invalid ", type="error"))
}
})
output$table <- renderTable({
if(input$submit == 0){ # when the submit button is not clicked
DF
}else{
if (n_row() >= 0 & n_row() <= 10) {
DF %>% head(n_row())
}
}
})
observeEvent(input$p_DFflt, { print(DF)} )
}
shinyApp(ui, server)
Related
I need a dataset to be continuously updated once the user clicks on a button. I was hoping the below code to achieve that but it simply ignores the updating part in my code. Here is the code:
library(shiny)
rm(list = ls())
x = 0.1
y = 0.1
df = data.frame(x,y) #Just define a simple dataset
ui <- shinyUI(fluidPage(
actionButton("run", "Run"),
tableOutput('table')
))
server <- shinyServer(function(input, output, session) {
df_new = eventReactive(input$run, {
z = runif(2)
if(isFALSE(exists("df_new()"))){ #Check if there is new data
return(rbind(df,z)) #1st update
}
else{
return(rbind(df_new(),z)) #Update the dataset
}
})
output$table = renderTable({
df_new()
})
})
shiny::shinyApp(ui, server)
I want the app to add a new row to the previous ones each time we run it, and so the number of rows should be always #of clicks + 1. Any idea if that's possible?
You could use a reactiveVal with observeEvent:
library(shiny)
x = 0.1
y = 0.1
df = data.frame(x,y) #Just define a simple dataset
ui <- shinyUI(fluidPage(
actionButton("run", "Run"),
tableOutput('table')
))
server <- shinyServer(function(input, output, session) {
df_new = reactiveVal(df)
observeEvent(input$run, {
z = runif(2)
df_new(rbind(df_new(),z))
})
output$table = renderTable({
df_new()
})
})
shiny::shinyApp(ui, server)
I'm making an app in which the user can create as many tables as he/she wants and display the code necessary to remake each individual table using shinymeta. I can generate the code for each of these tables but I have a problem when I want to create a complete modal that shows every code for each table.
To be clearer, here's a reproducible example:
library(shiny)
library(dplyr)
library(shinymeta)
module_ui <- function(id){
ns <- NS(id)
tagList(
fluidRow(
actionButton(ns("show_table"), "Show table"),
actionButton(ns("show_code"), "Show code"),
tableOutput(ns("table"))
)
)
}
module_server <- function(input, output, session){
data <- metaReactive2({
req(input$show_table)
isolate(metaExpr({
mtcars
}))
})
data2 <- metaReactive({
..(data()) %>%
select(mpg)
})
output$table <- renderTable({
data2()
})
observeEvent(input$show_code, {
showModal(modalDialog(
renderPrint({
expandChain(data(), data2())
})
))
})
return(data())
}
ui <- fluidPage(
actionButton("launch", "Launch"),
actionButton("show_full_code", "Show the full code (at least 2 'launch' before)")
)
server <- function(input, output, session) {
count <- reactiveValues(value = 0)
observeEvent(input$launch, {
count$value <- count$value + 1
insertUI(selector = "#show_full_code",
where = "afterEnd",
ui = module_ui(paste0("x", count$value)))
callModule(module_server, paste0("x", count$value))
})
#### "Merge" the single code modals in one big
observeEvent(input$show_full_code, {
showModal(modalDialog(
renderPrint({
expandChain(x1_data)
})
))
})
}
shinyApp(ui, server)
When you click on "Launch", two buttons are generated and you can display a table ("Show table") and the code to remake this table ("Show code"). You can click on "Launch" indefinitely and the table will be named x1_data, x2_data, etc.
However, when I try to generate the code that unites every individual code (by clicking on "Show the full code"), x1_data is not found. Using x1_data() does not work either. I'm not a fan of asking two questions in one post but I will do this now:
How can I access the reactive elements created inside modules?
How can I "merge" every individual code in a big one?
Also asked on RStudio Community
Edit: following a comment, I add a second reactive expression in my example, so that I can't use return on both of them.
Ok, I came up with an answer that has the module return the expandChain() results rather than trying to render them again in the server:
library(shiny)
library(dplyr)
library(shinymeta)
module_ui <- function(id){
ns <- NS(id)
tagList(
fluidRow(
actionButton(ns("show_table"), "Show table"),
actionButton(ns("show_code"), "Show code"),
tableOutput(ns("table"))
)
)
}
module_server <- function(input, output, session){
data <- metaReactive2({
req(input$show_table)
isolate(metaExpr({
mtcars
}))
})
data2 <- metaReactive({
..(data()) %>%
select(mpg)
})
output$table <- renderTable({
data2()
})
observeEvent(input$show_code, {
showModal(modalDialog(
renderPrint({
expandChain(data(), data2())
})
))
})
########################################
### create list of reactive objects ####
########################################
return(list(
expandChain(data(), data2())
)
)
}
ui <- fluidPage(
actionButton("launch", "Launch"),
actionButton("show_full_code", "Show the full code (at least 2 'launch' before)")
)
server <- function(input, output, session) {
count <- reactiveValues(value = 0)
observeEvent(input$launch, {
count$value <- count$value + 1
insertUI(selector = "#show_full_code",
where = "afterEnd",
ui = module_ui(paste0("x", count$value)))
callModule(module_server, paste0("x", count$value))
})
#### "Merge" the single code modals in one big list object
my_data <- reactive({
req(count$value)
my_set <- 1:count$value
### lapply through the different name spaces so all are captured ###
final <- lapply(my_set, function(x){
temp <- callModule(module_server, paste0("x", x))
return(temp)
})
return(final)
})
#### "Merge" the single code modals in one big
observeEvent(input$show_full_code, {
showModal(modalDialog(
renderPrint({
temp <- sapply(unlist(my_data()), function(x){
print(x)
})
})
))
})
}
shinyApp(ui, server)
I have created a large number of data tables using mapply, however, I need to access the data tables in a following step. R assigns random IDs to these tables if the user does not specify the IDs. Here is an example of what I would like to do:
library(shiny)
ui <- fluidPage(
h2("Last clicked:"),
verbatimTextOutput("last_clicked"),
actionButton("reset", "Reset clicked value"),
h2("Datatable:"),
DT::dataTableOutput("dt")
)
server <- function(input, output) {
# the last clicke value
output$last_clicked <- renderPrint({
str(last())
})
output$dt <- DT::renderDataTable({
DT::datatable(head(mtcars, 2), elementId = "DT_Test")
})
observeEvent(input$dt_cell_clicked, {
validate(need(length(input$dt_cell_clicked) > 0, ''))
print("You clicked something!")
})
myProxy = DT::dataTableProxy('dt')
last = reactiveVal(NULL)
observe({
last(input$dt_cell_clicked)
})
observeEvent(input$reset, {
DT::selectRows(myProxy, NULL)
last(NULL)
output$dt <- DT::renderDataTable({
DT::datatable(head(mtcars, 2))
})
})
}
shinyApp(ui, server)
If I look at the html, the elementID did not change to what I wanted, in fact, R gives the warning:
Warning in origRenderFunc() :
Ignoring explicitly provided widget ID "DT_Test"; Shiny doesn't use them
Even after the call, still not sure what you are trying to do.
But if you have a list of datatables and you want to access them, it works rather well like this:
library(shiny)
library(purrr)
ui <- fluidPage(
h2("Last clicked:"),
verbatimTextOutput("last_clicked"),
h2("elementId values"),
verbatimTextOutput("elementId_values"),
actionButton("reset", "Reset clicked value"),
h2("Datatable:"),
DT::dataTableOutput("dt")
)
server <- function(input, output) {
# the last clicke value
output$last_clicked <- renderPrint({
str(last())
})
table <- DT::datatable(head(mtcars, 2), elementId = "DT_Test")
table2 <- DT::datatable(tail(mtcars, 1), elementId = "DT_Test2")
list_of_data_tables <- list(table, table2)
element_ids <- purrr::map(list_of_data_tables, "elementId")
output$elementId_values <- renderPrint({
element_ids
})
output$dt <- DT::renderDataTable({
list_of_data_tables[[which(element_ids == "DT_Test2")]]
})
observeEvent(input$dt_cell_clicked, {
validate(need(length(input$dt_cell_clicked) > 0, ''))
print("You clicked something!")
})
myProxy = DT::dataTableProxy('dt')
last = reactiveVal(NULL)
observe({
last(input$dt_cell_clicked)
})
observeEvent(input$reset, {
DT::selectRows(myProxy, NULL)
last(NULL)
output$dt <- DT::renderDataTable({
DT::datatable(head(mtcars, 2))
})
})
}
shinyApp(ui, server)
I was trying to switch the label of a show/hide columns button, and also keep the track of the number of times it is clicked in order to alter the number of columns showed of a table. I made it, but I couldn't use a direct even/odd differentiation of the value of the counter. Instead I had to use this: (vars$counter+1)/2) %% 2 == 0) to make it work, because each click changes the counter 2 times. I would like to request an easier procedure, maybe there is a shinyBS for that?
## app.R ##
library(shiny)
library(shinydashboard)
library(DT)
body<-dashboardBody(
textOutput("count"),
uiOutput('showallcolumnsbutton'),
DT::dataTableOutput('table2')
)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(),
body
)
server <- function(input, output) {
table<-data.frame(replicate(10,sample(0:1,1000,rep=TRUE)))
vars<-reactiveValues()
vars = reactiveValues(counter = 0)
observe({
if(!is.null(input$showallcolumns)){
input$showallcolumns
isolate({
vars$counter <- vars$counter + 1
})
}
})
label <- reactive({
if(!is.null(input$showallcolumns)){
if( ( (vars$counter+1)/2) %% 2 == 0) label <- "Hide"
else label <- "Show"
}
})
output$showallcolumnsbutton <- renderUI({
actionButton("showallcolumns", label = label(),
icon("hand-pointer-o"),
style="color: #000; background-color: #0099ff; border-color: #2e6da4"
)
})
output$count<-renderText({paste("counter value:",vars$counter)})
columnstoshow = reactive ({
x= ((vars$counter+1)/2) # %% 2 == 0)
if (!is.null (x))
{
if (x %% 2 == 0) {
c=c(1:10)
}
else {
c=c(1:5)
}
} #end 1st if
else {
c=c(1:10)
}
})
output$table2 = DT::renderDataTable({
DT::datatable(table[, columnstoshow()])
})
} # end server
shinyApp(ui, server)
Since Im not 100% what you want, is this it? Note that I used other library such as shinyBS
rm(list = ls())
library(shiny)
library(shinydashboard)
library(DT)
library(shinyBS)
body <- dashboardBody(bsButton("showallcolumns", label = "Hide", block = F, style="danger",icon=icon("hand-pointer-o")),br(),DT::dataTableOutput('table2'))
ui <- dashboardPage(dashboardHeader(),dashboardSidebar(),body)
server <- function(input, output,session) {
table <- data.frame(replicate(10,sample(0:1,1000,rep=TRUE)))
vars <- reactiveValues(counter = 1:10)
observeEvent(input$showallcolumns,{
if(input$showallcolumns %% 2){
updateButton(session, "showallcolumns",label = "Show", block = F, style = "success",icon=icon("hand-pointer-o"))
vars$counter <- 1:5
}
else{
updateButton(session, "showallcolumns",label = "Hide", block = F, style = "danger",icon=icon("hand-pointer-o"))
vars$counter <- 1:10
}
})
output$table2 = DT::renderDataTable({
DT::datatable(table[, vars$counter])
})
} # end server
shinyApp(ui, server)
I have a R Shiny app that contains checkboxGroupInput, and I'm trying to create a "select all" button, using updateCheckboxGroupInput function.
You can see the full code below, but basically I defined the cb groups like this:
checkboxGroupInput("campaigns","Choose campaign(s):",campaigns_list)
and then, on a button click, call the function:
updateCheckboxGroupInput(session,"campaigns","Choose campaign(s):",choices=campaigns_list,selected=campaigns_list)
I have an indication that the function ran, but what it does is actually UNselecting the checkboxes.
BTW, when I put the selected upon defining the cbGroupInput it did worked, but not on the function.
Thanks!
this is my server.R:
library(shiny)
source('usefulFunctions.R')
shinyServer(function(input, output, session) {
output$cascading <- renderUI({
provider_id <- input$provider
if (provider_id == "") return(NULL)
campaigns_list <<- t(getCampaigns(provider_id))
tagList(
checkboxGroupInput("campaigns","Choose campaign(s):",
choices = campaigns_list, selected = campaigns_list),
actionLink("selectall","Select All")
)
})
observe({
if(is.null(input$selectall)) return(NULL)
if (input$selectall > 0)
{
print(campaigns_list)
updateCheckboxGroupInput(session,"campaigns","Choose campaign(s):",choices=campaigns_list,selected=campaigns_list)
}
})
})
I also added the select and unselect options here by checking if the button or link are divisible by 2
#rm(list = ls())
library(shiny)
campaigns_list <- letters[1:10]
ui =fluidPage(
checkboxGroupInput("campaigns","Choose campaign(s):",campaigns_list),
actionLink("selectall","Select All")
)
server = function(input, output, session) {
observe({
if(input$selectall == 0) return(NULL)
else if (input$selectall%%2 == 0)
{
updateCheckboxGroupInput(session,"campaigns","Choose campaign(s):",choices=campaigns_list)
}
else
{
updateCheckboxGroupInput(session,"campaigns","Choose campaign(s):",choices=campaigns_list,selected=campaigns_list)
}
})
}
runApp(list(ui = ui, server = server))
If campaigns_list is a list, might be because you are specifying the list of all your choices instead of the value of the boxes that should be selected in the selected argument of your updateCheckboxGroupInput.
Try replacing selected=campaigns_list by selected=unlist(campaigns_list).
Here is an example with dummy names:
library(shiny)
server<-function(input, output,session) {
observe({
if(input$selectall == 0) return(NULL)
else if (input$selectall > 0)
{
variables<-list("Cylinders" = "cyl","Transmission" = "am","Gears" = "gear")
updateCheckboxGroupInput(session,"variable","Variable:",choices=variables,selected=unlist(variables))
}
})
}
ui <- shinyUI(fluidPage(
checkboxGroupInput("variable", "Variable:",list("Cylinders" = "cyl","Transmission" = "am","Gears" = "gear")),
actionButton("selectall", "Select All")
))
shinyApp(ui = ui, server = server)