I am trying to implement an app for making a test. The app will relay on a random generation of data on which the questions are formulated and, in this particular case a single choice multiple selection question is implemented. There is an actionButton that triggers the generation of new questions and also an actionButton which evaluates the selected answer.
Here is the app:
library(pacman)
p_load(here)
p_load(tidyverse)
p_load(shiny)
p_load(plotly)
p_load(stringi)
##########################################################
### generate the questions with its evaluations
### a random sample of these will be used in the app
lore<-stri_rand_lipsum(1, start_lipsum = TRUE)
questions<-substring(lore, seq(1, nchar(lore), 25), seq(25, nchar(lore), 25)) %>% {.[1:10]}
dic<-data.frame(id=letters[1:10],quest=questions,out=sample(c(T,F),10,replace = T))
##########################################################
ui <- fluidPage(
titlePanel("exam test"),
sidebarLayout(
sidebarPanel(
actionButton("sim",label ="generate questions"),
uiOutput('resetable_input'),
actionButton("run",label ="evaluate")
),
mainPanel(
h3("you selected"),
textOutput("ans1"),
h3("correct?"),
textOutput("eval1"),
h3("the answer is"),
textOutput("sol1")
)
)
)
server <- function(input, output, session){
### build radioButtons based on a sample from dic df.
output$resetable_input <- renderUI({
times <- input$sim
temp_ind<- c( sample(which(dic$out),1),sample(which(!dic$out),3) )
temp_ind<-sample(temp_ind)
div(id=letters[(times %% length(letters)) + 1],
radioButtons("someb","Lorem ipsum dolor sit amet?",choiceNames=dic[temp_ind,"quest"],choiceValues=dic[temp_ind,"id"])
)
})
res_react<-eventReactive(
input$run,{
list(sel=dic[which(dic[,"id"]==input$someb),"quest"],
eval1=dic[which(dic[,"id"]==input$someb),"out"],
### here I don't know how to get the correct answer to display
sol="?")
}
)
output$ans1 <- renderText({ res_react()[["sel"]] })
output$eval1 <- renderText({ res_react()[["eval1"]] })
output$sol1 <- renderText({ res_react()[["sol"]] })
}
shinyApp(ui = ui, server = server)
The problem that I am facing is that I cannot get access to the whole set of available options from the radioButtons (id someb) in order to provide the correct answer in the last textOutput (output$sol1). I checked this out however I don't think this could be useful here since the available options must change each time the actionButton is activated.
Any advice is appreciated as always.
One option to achieve your desired result would be to use a reactiveVal to store the question data. To this end I first added a function generate_question. This function could first be used to init the reactiveVal when the app starts. Second, I added an observeEvent to generate a new question if the user requests so and updates the reactiveVal accordingly.
library(stringi)
library(shiny)
set.seed(123)
lore <- stri_rand_lipsum(1, start_lipsum = TRUE)
questions <- substring(lore, seq(1, nchar(lore), 25), seq(25, nchar(lore), 25))[1:10]
dic <- data.frame(id = letters[1:10], quest = questions, out = sample(c(T, F), 10, replace = T))
ui <- fluidPage(
titlePanel("exam test"),
sidebarLayout(
sidebarPanel(
actionButton("sim", label = "generate questions"),
uiOutput("resetable_input"),
actionButton("run", label = "evaluate")
),
mainPanel(
h3("you selected"),
textOutput("ans1"),
h3("correct?"),
textOutput("eval1"),
h3("the answer is"),
textOutput("sol1")
)
)
)
generate_question <- function() {
answers <- sample(c(sample(which(dic$out), 1), sample(which(!dic$out), 3)))
dic[answers, ]
}
server <- function(input, output, session) {
question <- reactiveVal(generate_question())
observeEvent(input$sim, {
question(generate_question())
})
output$resetable_input <- renderUI({
req(question())
div(
id = "quest",
radioButtons("someb", "Lorem ipsum dolor sit amet?",
choiceNames = question()[["quest"]],
choiceValues = question()[["id"]]
)
)
})
res_react <- eventReactive(
input$run,
{
list(
sel = question()[question()$id == input$someb, "quest"],
eval1 = question()[question()$id == input$someb, "out"],
sol = question()[question()$out, "quest"]
)
}
)
output$ans1 <- renderText({
res_react()[["sel"]]
})
output$eval1 <- renderText({
res_react()[["eval1"]]
})
output$sol1 <- renderText({
res_react()[["sol"]]
})
}
shinyApp(ui = ui, server = server)
Related
I am a beginer of shiny, and I am building a shiny app using win10 system, rstudio, and shiny version 1.7.1. I would like to make it more user oriented. It means that other parts of the application will be hid unless user uploads correct data. After many attempts, I decided to use session$userData and shinyjs::toggle to develop this app. But I am confused by session$userData. In the beginning, by reading the official documentation, I think it just like the global environment of r. But obviously not. So I just want to know how to use it correctly, or how to realize the features I want. There are three examples I had tried, they are for your reference.
Please note that the third example is almost what I want, but I don't think it's elegant since the continue button is somewhat redundant.
Examples 1:
I would like to check whether there is data input or whether the input data is a csv format, if true, show the data, and if not, the rest part of the app will be hid. In this case you can see, although you data have passed the check, the tablepanel b will still show nothing, unless before input data you have clicked tablepanel b, or unless after data checking you clicked button go again.
##### 1. packages #####
library(shiny)
library(shinyjs)
##### 2. ui #####
ui <- fluidPage(
useShinyjs(),
tabsetPanel(
tabPanel("a",
sidebarLayout(
sidebarPanel(uiOutput("ui_p1_sidebar1"), uiOutput("ui_p1_sidebar2")),
mainPanel(uiOutput("ui_p1_main"))
)),
tabPanel("b",
sidebarLayout(
sidebarPanel(uiOutput("ui_p2_sidebar")),
mainPanel(uiOutput("ui_p2_main"))
))
)
)
##### 3. server #####
server <- function(input, output, session) {
output$ui_p1_sidebar1 <- renderUI({
fileInput(inputId = "p1s_inputdata",
label = "Input data",
multiple = FALSE,
accept = ".csv")
})
output$ui_p1_sidebar2 <- renderUI({
shiny::actionButton(inputId = "p1s_go",
label = "go",
icon = icon("play"))
})
observeEvent(input$p1s_go,{
isolate({
data <- input$p1s_inputdata
})
output$ui_p1_main <- renderUI({
tagList(
h3("Data check: "),
verbatimTextOutput(outputId = "p1m_datacheck", placeholder = T),
h3("Data show: "),
verbatimTextOutput(outputId = "p1m_datashow", placeholder = T),
)
})
output$p1m_datacheck <- renderPrint({
# data check part, the result of checking is stored by session$userData$sig
if(is.null(data)){
cat("There is no data input! \n")
session$userData$sig <- F
} else{
dataExt <- tools::file_ext(data$name)
if(dataExt != "csv"){
cat("Please input csv data! \n")
session$userData$sig <- F
} else{
cat("Data have passed the check!")
session$userData$data <- read.csv(data$datapath)
session$userData$sig <- T
}
}
})
output$p1m_datashow <- renderPrint({
if(session$userData$sig){
print(session$userData$data)
} else{
cat("Please check the data!")
}
})
output$ui_p2_sidebar <- renderUI({
radioButtons("aaa", "aaa", choices = c("a", "b", "c"))
})
output$ui_p2_main <- renderUI({
verbatimTextOutput(outputId = "p2m_print", placeholder = T)
})
output$p2m_print <- renderPrint({print(letters[1:10])})
observe({
toggle(id = "ui_p2_sidebar", condition = session$userData$sig)
toggle(id = "ui_p2_main", condition = session$userData$sig)
})
})
}
##### 4. app #####
shinyApp(ui = ui, server = server)
Example 2:
In this small case you can see, in a samle module, session$userData$... changed timely, but in another module, it will not change unless you click the button again. It that means session$userData$... could have different values at the same time?
##### 1. packages #####
library(shiny)
##### 2. ui #####
ui <- fluidPage(
sidebarLayout(
sidebarPanel(uiOutput("ui_sidebar")),
mainPanel(uiOutput("ui_main1"), uiOutput("ui_main2"))
)
)
##### 3. server #####
server <- function(input, output, session) {
output$ui_sidebar <- renderUI({
tagList(
radioButtons("s_letter", "letters", choices = c("a", "b", "c")),
shiny::actionButton(inputId = "go1",
label = "GO1",
icon = icon("play"))
)
})
observeEvent(input$go1, {
output$ui_main1 <- renderUI({
tagList(
h3("module 1: shared value changes timely."),
verbatimTextOutput(outputId = "m1", placeholder = T),
h3("module 2: shared value changes by button."),
verbatimTextOutput(outputId = "m2", placeholder = T)
)
})
output$m1 <- renderPrint({
out <- switch (input$s_letter,
"a" = "choose a",
"b" = "choose b",
"c" = "choose c")
session$userData$sharedout <- out
cat("out: \n")
print(out)
cat("sharedout: \n")
print(session$userData$sharedout)
})
output$m2 <- renderPrint({
cat("sharedout: \n")
print(session$userData$sharedout)
})
})
}
##### 4. app #####
shinyApp(ui = ui, server = server)
Example 3: I also tried other solutions. There is a modification of example 1, I have added a continue button to realize my thought. It works well, but I hope the hidden action is based on conditions rather than events. So how to remove the button and let the rest part displayed automatically if data passed checking?
##### 1. packages #####
library(shiny)
##### 2. ui #####
ui <- fluidPage(
tabsetPanel(
tabPanel("a",
sidebarLayout(
sidebarPanel(uiOutput("ui_p1_sidebar1"), uiOutput("ui_p1_sidebar2")),
mainPanel(uiOutput("ui_p1_main"))
)),
tabPanel("b",
sidebarLayout(
sidebarPanel(uiOutput("ui_p2_sidebar")),
mainPanel(uiOutput("ui_p2_main"))
))
)
)
##### 3. server #####
server <- function(input, output, session) {
output$ui_p1_sidebar1 <- renderUI({
fileInput(inputId = "p1s_inputdata",
label = "Input data",
multiple = FALSE,
accept = ".csv")
})
output$ui_p1_sidebar2 <- renderUI({
shiny::actionButton(inputId = "p1s_go",
label = "go",
icon = icon("play"))
})
observeEvent(input$p1s_go,{
isolate({
data <- input$p1s_inputdata
})
output$ui_p1_main <- renderUI({
tagList(
h3("Data check: "),
verbatimTextOutput(outputId = "p1m_datacheck", placeholder = T),
uiOutput("ispass"),
h3("Data show: "),
verbatimTextOutput(outputId = "p1m_datashow", placeholder = T)
)
})
output$p1m_datacheck <- renderPrint({
if(is.null(data)){
cat("There is no data input! \n")
session$userData$sig <- F
} else{
dataExt <- tools::file_ext(data$name)
if(dataExt != "csv"){
cat("Please input csv data! \n")
session$userData$sig <- F
} else{
cat("Data have passed the check!")
session$userData$data <- read.csv(data$datapath)
session$userData$sig <- T
}
}
})
output$ispass <- renderUI({
if(isFALSE(session$userData$sig)){
return()
} else{
shiny::actionButton(inputId = "ispass",
label = "continue",
icon = icon("play"))
}
})
})
observeEvent(input$ispass,{
output$p1m_datashow <- renderPrint({
if(session$userData$sig){
print(session$userData$data)
} else{
cat("Please check the data!")
}
})
output$ui_p2_sidebar <- renderUI({
radioButtons("aaa", "aaa", choices = c("a", "b", "c"))
})
output$ui_p2_main <- renderUI({
verbatimTextOutput(outputId = "p2m_print", placeholder = T)
})
output$p2m_print <- renderPrint({print(letters[1:10])})
})
}
##### 4. app #####
shinyApp(ui = ui, server = server)
I hope the following refactoring will help and does what you want.
An essential tool for hiding,showing and updating UI elements can be the renderUI, but often this is overkill because of rerenderings.
But I would suggest using the shinyjs-package which gives you functions like shinyjs::show and shinyjs::hide for showing and hiding. For updating UI-elements, there are functions like shiny::updateActionButton,shiny::updateCheckboxInput, shiny::updateRadioButtons, ....
It is (always) useful to give your UI-elements IDs, like the tabsetPanel.
Moreover, a nice tool too is shiny::conditionalPanel, but you will dive into all this stuff when programming more apps. :)
##### 1. packages #####
library(shiny)
myapp <- function() {
##### 2. ui #####
ui <- fluidPage(
tabsetPanel(
tabPanel("a",
sidebarLayout(
sidebarPanel(
fileInput(inputId = "p1s_inputdata", label = "Input data", multiple = FALSE, accept = ".csv")
),
mainPanel(uiOutput("ui_p1_main"))
)),
tabPanel("b",
sidebarLayout(
sidebarPanel(radioButtons("aaa", "aaa", choices = c("some", "placeholder", "stuff"))),
mainPanel(verbatimTextOutput(outputId = "p2m_print", placeholder = T))
)),
id = "TABSETPANEL"
)
)
##### 3. server #####
server <- function(input, output, session) {
shiny::hideTab(inputId = "TABSETPANEL", target = "b", session = session)
observeEvent(input$p1s_inputdata, {
data <- input$p1s_inputdata
dataCheckText <- NULL
if(is.null(data)){
dataCheckText <- "There is no data input!"
session$userData$sig <- F
} else{
dataExt <- tools::file_ext(data$name)
if(dataExt != "csv"){
dataCheckText <- "Please input csv data!"
session$userData$sig <- F
} else{
dataCheckText <- "Data have passed the check!"
session$userData$data <- read.csv(data$datapath)
session$userData$sig <- T
}
}
output$p1m_datacheck <- renderPrint(dataCheckText)
if(session$userData$sig) shiny::showTab(inputId = "TABSETPANEL", target = "b", session = session)
else shiny::hideTab(inputId = "TABSETPANEL", target = "b", session = session)
main1Taglist <- tagList(
h3("Data check: "),
verbatimTextOutput(outputId = "p1m_datacheck", placeholder = T)
)
if(session$userData$sig) {
shiny::showTab(inputId = "TABSETPANEL", target = "b", session = session)
output$p1m_datashow <- renderPrint({
print(session$userData$data)
})
main1Taglist <- c(main1Taglist, tagList(
h3("Data show: "),
verbatimTextOutput(outputId = "p1m_datashow", placeholder = T)
))
#Update stuff in panel b according to the new data
updateRadioButtons(session = session, inputId = "aaa", choices = names(session$userData$data))
output$p2m_print <- renderPrint({print(letters[1:10])})
}
output$ui_p1_main <- renderUI(main1Taglist)
})
}
##### 4. app #####
shinyApp(ui = ui, server = server)
}
myapp()
You're somewhat on the right track. Try something like this:
observeEvent(input$go1, {
# Perform data validation here.
# This would look similar to what you have inside output$p1m_datacheck <- renderPrint({})
# If data file is no good, do nothing, exit this function: return()
# Else, data file is good, continue
# Do your output$* <- render*() functions here
})
You don't need to isolate() inside the handlerExpr of observeEvent(). It will already be executed in an isolate() scope.
I am new to Shiny. What I want to do in my application is, running & displaying some part of the code only when a condition on another calculation is met.
The conditionalPanel works fine with the conditions on input values but I could not figure out how to do this with the 'output' values, i.e., conditionally on the output values of the functions. Below is my example code:
library(shiny)
msLocation <- "msLoc"
searchMWText <- "searchMW"
bid <- "2333333"
fulltext <- "fullDisplay"
ui <- fluidPage(
titlePanel("Run server codes conditionally"),
sidebarLayout(
sidebarPanel(
helpText("Evaluate input and run different parts of the code depending on the output functions"),
br(),
sliderInput("rand", "select seed", min = 1, max = 50, step = 1, value = 1)
),
mainPanel(
fluidRow(conditionalPanel("output.rand == 1"),
tags$h4("Here comes the default part"),
br(),
textOutput("defaultCalc")),
fluidRow(conditionalPanel("output.randomint != 1",
tags$h4("I can evaluate if the chosen number is even or odd."),
br(),
textOutput("evenodd")
),
fluidRow(conditionalPanel("output.evenodd == 'Number is even'",
tags$h4("Number even calculation "),
textOutput("msLoc"),
br(),
textOutput("searchMW"),
br(),
textOutput("defaultID"),
br()
),
fluidRow(conditionalPanel("output.evenodd == 'Number is odd'",
tags$h4("Here is some id:", textOutput("id")),
textOutput("displayFull")
)
)
)
)
)))
#
server <- function(input, output) {
rand1 <- reactive({
if(is.null(input$rand)){return(NULL)}
rn <- input$rand
return(rn)
})
randomint <- reactive({
seedn <- rand1()
set.seed(seedn)
rint <- sample(1:50, 1)
return(rint)
})
calc1 <- reactive({
intn <- randomint()
modn <- intn %% 2
return(modn)
})
evenOdd <- reactive({
modn <- calc1()
if(modn == 0){valueText = "Number is even"}
if(modn != 0){valueText = "Number is odd"}
return(valueText)
})
idtext <- reactive({
idint <- sample(1:10000, 3)
idint <- as.character(idint)
idint <- paste(idint, collapse = "")
return(idint)
})
output$defaultCalc <- renderText({
as.character(randomint())
})
output$evenodd <- renderText({
evenOdd()
})
output$searchMW <- renderText({
searchMWText
})
output$defaultID <- renderText({
bid
})
output$id <- renderText({
idtext()
})
output$displayFull <- renderText({
fulltext
})
}
shinyApp(ui = ui, server = server)
The problem is, the parts after default always appear, e..g., 'Here is some id' text always appears and this is not what I want. I want to display 'Here is some id' and run the calculation (idtext) only when the number is odd.The number is not coming from the slider input, the slider input is providing the seed only. The number is also calculated and depends on its value, the other parts should be run and displayed. Until the user selects a slider input value, only the 'default part' should be displayed and nothing else.
I searched a lot and could not find a solution that mentions the conditions on output. What is the best way to solve this?
Do:
randomint <- reactive({
seedn <- rand1()
set.seed(seedn)
rint <- sample(1:50, 1)
return(rint)
})
output$randomint <- reactive(randomint())
outputOptions(output, "randomint", suspendWhenHidden = FALSE)
Then you can use "output.randomint !== 1".
Is there a way to show the value from textInput() elsewhere in the UI without having to go through server.R with something very verbose like the following?
ui.R
library(shiny)
shinyUI(
fluidPage(
textInput('text_in', label = 'Write text here'),
# elsewhere in the UI...
textOutput('text_out')
))
server.R
library(shiny)
shinyServer(function(input, output) {
output$text_out = renderText(input$text_in)
})
It's not too bad for this example, but it becomes very verbose when I need to do it many times. My desire is to collect all the inputs the user enters throughout the app and compile them into a nice table at the end so they can confirm everything is laid out right.
I've seen you can reference input elements without going through the server when using a JavaScript expression in conditionalPanel() but I'm not sure how to implement that outside of this specific instance.
For accessing all inputs, you can use reactiveValuesToList server-side. You can access input values via Javascript Events like below (I have taken the example from #Pork Chop) :
library(shiny)
ui <- basicPage(
fluidRow(
column(
width = 6,
textInput('a', 'Text A',"a1"),
textInput('b', 'Text B',"b1"),
textInput('c', 'Text A',"c1"),
textInput('d', 'Text B',"d1"),
textInput('e', 'Text A',"e1"),
textInput('f', 'Text B',"f1")
),
column(
width = 6,
tags$p("Text A :", tags$span(id = "valueA", "")),
tags$script(
"$(document).on('shiny:inputchanged', function(event) {
if (event.name === 'a') {
$('#valueA').text(event.value);
}
});
"
),
tableOutput('show_inputs')
)
)
)
server <- shinyServer(function(input, output, session){
AllInputs <- reactive({
x <- reactiveValuesToList(input)
data.frame(
names = names(x),
values = unlist(x, use.names = FALSE)
)
})
output$show_inputs <- renderTable({
AllInputs()
})
})
shinyApp(ui = ui, server = server)
Since your overall objective is to collect all the user inputs and then compile them into a table I will show you how to achieve that with example below. As you can see all of the input variables can be accessed by names from server. I kept them in a reactive just in case you need it for further analysis or for some renderUI functionality.
#rm(list=ls())
library(shiny)
ui <- basicPage(
textInput('a', 'Text A',"a1"),
textInput('b', 'Text B',"b1"),
textInput('c', 'Text A',"c1"),
textInput('d', 'Text B',"d1"),
textInput('e', 'Text A',"e1"),
textInput('f', 'Text B',"f1"),
tableOutput('show_inputs')
)
server <- shinyServer(function(input, output, session){
AllInputs <- reactive({
myvalues <- NULL
for(i in 1:length(names(input))){
myvalues <- as.data.frame(rbind(myvalues,(cbind(names(input)[i],input[[names(input)[i]]]))))
}
names(myvalues) <- c("User Input","Last Value")
myvalues
})
output$show_inputs <- renderTable({
AllInputs()
})
})
shinyApp(ui = ui, server = server)
If the Shiny inputs all have different lengths and the above does not work (e.g. if you have combination of radio buttons, checkboxgroup, textInput, etc.) this will work and can produce a table of variable:value that you can parse later:
AllInputs <- reactive({
myvalues <- NULL
newvalues <- NULL
for(i in 1:length(names(input))){
newvalues <- paste(names(input)[i], input[[names(input)[i]]], sep=":")
myvalues <- append(myvalues, newvalues)
}
myvalues
})
output$show_inputs <- renderTable({
AllInputs()
})
Borrowing from both Pork Chop and mysteRious, here's a solution that works for multiple types of text & number inputs in shiny.
library(shiny)
AdvRchp3 <- "While you’ve probably already used many (if not all)
of the different types of vectors, you may not have thought
deeply about how they’re interrelated. In this chapter,
I won’t cover individual vectors types in too much detail,
but I will show you how all the types fit together as a whole.
If you need more details, you can find them in R’s documentation."
ui <- fluidPage(
fluidRow(
h4("Text Inputs"),
textInput("text_input", "Input some Text", value = "some text"),
passwordInput("password_input", "Input a Password", value = "1234"),
textAreaInput("text_area_input", "Input lots of Text", rows = 3, value = AdvRchp3)
),
fluidRow(
h4("Numeric Inputs"),
numericInput("numeric_input", "Number 1", value = 1, min = 0, max = 100),
sliderInput("slider_input_single", "Number 50", value = 50, min = 0, max = 100),
sliderInput("slider_input_ranges", "Range 10 to 20", value = c(10, 20), min = 0, max = 100)
),
fluidRow(
tableOutput("show_inputs")
)
)
server <- function(input, output, session) {
all_inputs <- reactive({
input_df <- NULL
df_row <- NULL
for(i in 1:length(names(input))){
df_row <- as.data.frame(cbind(names(input)[i], input[[names(input)[i]]]))
input_df <- as.data.frame(dplyr::bind_rows(input_df, df_row))
}
names(input_df) <- c("input_id", "input_val")
input_df
})
output$show_inputs <- renderTable({
all_inputs()
})
}
shinyApp(ui, server)
notice: the rbind is now dplyr::bind_rows, but plyr::rbind.fill will also work.
first I know there is a lot of threads covering my problem, I read them all, but I did not manage to do it. I got a list of 10 data.frame which I built through the following code :
list_of_df=list()
for (i in seq(1,10)){
number_row=sample(seq(5,10),size = 1)
num=seq(1,number_row)
val=sample(x = letters,size = number_row,replace = TRUE )
df=data.frame(num=num,
val=val)
rownames(df)=NULL
list_of_df[[i]]=df
}
I want the user to enter n, the number of tables he wants to see. And then display n random tables from the list_of_df. I want to display those tables inside tabs. Here is what I did, I grabbed some ideas here and there, but obviously it does not work and I do not know why.
library(shiny)
# ui function
ui = pageWithSidebar(
headerPanel('Dynamic Tabs'),
sidebarPanel(
numericInput(inputId = "numput",label = "number of tables",value = 1,min = 1,max = 5)
),
mainPanel(
uiOutput('mytabs')
)
)
# server function
server = function(input, output, session){
random_tables<- reactive({
index=sample(seq(1,10),size = input$numput,replace=FALSE)
list_of_df[[index]]
})
size<-reactive({
length(random_tables())
})
for (i in 1:size()) {
local({
my_i <- i
tablename <- paste("table_", my_i, sep="")
output[[tablename]] <- renderTable({
random_tables()[[i]]
})
})
}
output$mytabs = renderUI({
nTabs = size()
myTabs = lapply(paste0('table_', 1: nTabs), function(x){
tabPanel(x, tableOutput(x))
})
do.call(tabsetPanel, myTabs)
})
}
shinyApp(ui, server)
So, if you see what I should do ...
Here is a working version:
library(shiny)
# ui function
ui = pageWithSidebar(
headerPanel('Dynamic Tabs'),
sidebarPanel(
numericInput(inputId = 'numput',label = "number of tables",value = 1,min = 1,max = 5)
),
mainPanel(
uiOutput('mytabs')
)
)
# server function
server = function(input, output, session){
list_of_df=list()
for (i in seq(1,10)){
number_row=sample(seq(5,10),size = 1)
num=seq(1,number_row)
val=sample(x = letters,size = number_row,replace = TRUE )
df=data.frame(num=num,
val=val)
rownames(df)=NULL
list_of_df[[i]]=df
}
random_tables<- reactive({
index=sample(seq(1,10),size = input$numput,replace=FALSE)
list_of_df[index]
})
size<-reactive({
input$numput
})
observe({
lapply(seq_len(size()), function(i) {
local({
my_i <- i
tablename <- paste("table_", my_i, sep="")
output[[tablename]] <- renderTable({
random_tables()[[i]]
})
})
})
})
output$mytabs = renderUI({
nTabs = size()
myTabs = lapply(paste0('table_', seq_len(nTabs)), function(x){
tabPanel(x, tableOutput(x))
})
do.call(tabsetPanel, myTabs)
})
}
shinyApp(ui=ui,server=server)
A couple issues, you subset the list with double brackets, but it isn't working like you think it is, you need single brackets. Next when you select a single table random_table() is a data.frame so when you call length you get 2, the number of columns. So just use the input$numput for size() since they are the same anyways. Also, I put the dynamic output in an observe so that it can access the reactive size(). A small thing, but I used seq_len instead of 1:aNumber since it is more robust.
Hope this helps
How can I extract selected option from r markdown selectInput drop down menu? I have reactive input on my web page something like the following:
aggdata <- data.frame(
"Experiment" = c("One","Two","Three"),
"AnythingElse" = c(1,2,3)
)
selectInput("Experiment1","Choose the first experiment",
choices = unique(aggdata$Experiment),
selected = unique(aggdata$Experiment)[1])
reactiveData <- reactive(as.data.frame(subset(aggdata, Experiment == input$Experiment1)))
firstExperiment_aggData <- reactive(reactiveData())
And I'd like to write somewhere to the text reactively, what was user's selection. Do you happen to know, how can I do that. Many thanks in advance.
As far as Shiny is concerned, you could start with this. Does that help you?
library(shiny)
aggdata <- data.frame(
"Experiment" = c("One","Two","Three"),
"AnythingElse" = c(1,2,3)
)
ui <- shinyUI(
fluidPage(
selectInput("Experiment1","Choose the first experiment",
choices = unique(aggdata$Experiment),
selected = unique(aggdata$Experiment)[1]),
tableOutput("table1")
)
)
server <- shinyServer(function(input, output, session) {
reactiveData <- reactive({
return(as.data.frame(subset(aggdata, Experiment == input$Experiment1)))
})
output$table1 <- renderTable({
return( reactiveData() )
})
})
shinyApp(ui = ui, server = server)