I'm a Shiny newbie and I have probably a simple question, but I swear I spent half day reading solutions here and can't find anything close to what I need.
Imaging you have a database with employees ID, name, last name, age.
I need to have in my app a text input that allows the user to enter the ID and to see on the same row the name, last name and age.
The problem I face is that textInput will have a label (say "ID").
All the three other fields, that I need to be on the same row, won't have a label.
So what I would need is either a way to add a label to the three textOutput elements or to display them as textInput with a default value that has to change/behave like an output as soon as a user enters a new ID. But how?
This is my sample code:
library(shiny)
u <- fluidPage(
titlePanel("Simple Selectable Reactive Function"),
sidebarLayout(
sidebarPanel(),
mainPanel(
h2("Results"),
fluidRow(column(2,
textInput("input_ID", label = "Cusip 1",
value = "123")),
column(2,
textOutput(outputId = "output_name")),
column(2,
textOutput(outputId = "output_lastname")),
column(2,
textOutput(outputId = "output_age"))
)
)
)
)
s <- function(input,output){
output$output_name <- renderText(
{ # here is where I will check in a database
paste("Sample Name")
})
output$output_lastname <- renderText(
{ # here is where I will check in a database
paste("Sample Last Name")
})
output$output_age <- renderText(
{ # here is where I will check in a database
paste("Sample Age")
})
}
shinyApp(ui=u,server=s)
Perhaps I have to use different widgets?
Thank you
I updated the code to change the label using an textInput as suggested in the comment. Perhaps it helps to understand exactly what you are looking for.
library(dplyr)
library(shiny)
library(shinyjs)
u <- fluidPage(
titlePanel("Simple Selectable Reactive Function"),
sidebarLayout(
sidebarPanel(),
mainPanel(
h2("Results"),
fluidRow(
column(2, textInput("input_ID", label = "Cusip 1",value = "123")),
column(2, textInput("output_name", label = "Firstname") %>% disabled()),
column(2, textInput("output_lastname", label = "Lastname") %>% disabled()),
column(2, textInput("output_age", label = "Age") %>% disabled())))))
s <- function(input,output, session){
observe({
id <- input$input_ID
set.seed(id)
df <- list(firstname = sample(LETTERS, 1), lastname = sample(LETTERS, 1), age = sample(1:100, 1))
updateTextInput(session, inputId = "output_name", label = df[["firstname"]])
updateTextInput(session, inputId = "output_lastname", label = df[["lastname"]])
updateTextInput(session, inputId = "output_age", label = df[["age"]])
})
}
shinyApp(ui=u,server=s)
How I create label for my UI is simply adding a h3 tag above each textoutput:
library(shiny)
u <- fluidPage(
titlePanel("Simple Selectable Reactive Function"),
sidebarLayout(
sidebarPanel(),
mainPanel(
h2("Results"),
fluidRow(column(2,
textInput("input_ID", label = "Cusip 1",
value = "123")),
column(2,
h3("First Name: "),
textOutput(outputId = "output_name")),
column(2,
h3("Last Name: "),
textOutput(outputId = "output_lastname")),
column(2,
h3("Age: ),
textOutput(outputId = "output_age"))
)
)
)
)
Related
I am trying to create an app that will show you results depending on a selectInput and the changes are controlled by actionButtons.
When you launch the app, you have to select a choice: Data 1 or Data 2. Once you have selected your choice (e.g. Data 1), you have to click the actionButton "submit type of data". Next, you go to the second tab, choose a column and then click "submit".
The output will be: one table, one text and one plot.
Then, if you go back to the first tab and select "Data 2", everything that you have generated is still there (as it is expected, since you didn't click any button).
However, I would like to remove everything that is in the mainPanel if I change my first selectInput as you could see it when you launch the app for the first time.
The idea is that since you have changed your first choice, you will have to do the same steps again (click everything again).
I would like to preserve and control the updates with actionButtons as I have in my code (since I am working with really long datasets and I don't want to depend on the speed of loading things that I don't want until I click the button). Nevertheless, I cannot think a way to remove everything from mainPanel if I change the choice of the first selectInput.
Does anybody have an idea how I can achieve this?
Thanks in advance
Code:
library(shiny)
library(shinyWidgets)
library(shinyFeedback)
library(DT)
library(datasets)
ui <- fluidPage(
sidebarPanel(
tabsetPanel(id="histogram",
tabPanel("Selection",
useShinyFeedback(),
selectInput(inputId = "type", label = "Select your data",
choices = c("Data 1" = "data1",
"Data 2" = "data2")),
conditionalPanel(
condition = "input.type == 'data2'",
div(style = "position:absolute;right:2.5em;",
actionButton(
inputId = "button_more_info_data2",
label = "More info",
icon = icon("info-circle"))
)
),
actionButton(
inputId = "button",
label = "Submit type of data",
icon = icon("check")
)
),
tabPanel("Pick the column",
br(),
selectizeInput(inputId = "list_columns", label = "Choose the column:", choices=character(0)),
actionButton(
inputId = "button2",
label = "Submit")
))
),
mainPanel(
dataTableOutput("table"),
textOutput("text"),
plotOutput("myplot")
)
)
server <- function(input, output, session) {
observeEvent(input$type,{
feedbackWarning(inputId = "type",
show = ("data2" %in% input$type),
text ="This data is... Please, be careful..."
)
})
mydata <- reactive({
if(input$type == "data1"){
mtcars
}else{
iris
}
}) %>% bindEvent(input$button2)
# This is to generate the choices (gene list) depending on the user's input.
observeEvent(input$button, {
updateSelectizeInput(
session = session,
inputId = "list_columns",
choices = colnames(trees), options=list(maxOptions = length(colnames(trees))),
server = TRUE
)
})
output$table <- renderDataTable({
req(input$button2)
mydata()
})
output$text <- renderText({
req(input$button2)
input$list_columns
})
output$myplot <- renderPlot({
req(input$button2, input$button)
hist(trees[,input$list_columns])
})
}
if (interactive())
shinyApp(ui, server)
Here is an example using a reset button - using the selectInput you'll end up with a circular reference:
library(shiny)
library(shinyWidgets)
library(shinyFeedback)
library(DT)
library(datasets)
ui <- fluidPage(sidebarPanel(tabsetPanel(
id = "histogram",
tabPanel(
"Selection",
useShinyFeedback(),
selectInput(
inputId = "type",
label = "Select your data",
choices = c("Data 1" = "data1",
"Data 2" = "data2")
),
conditionalPanel(
condition = "input.type == 'data2'",
div(
style = "position:absolute;right:2.5em;",
actionButton(
inputId = "button_more_info_data2",
label = "More info",
icon = icon("info-circle")
)
)
),
actionButton(
inputId = "button",
label = "Submit type of data",
icon = icon("check")
),
actionButton(
inputId = "reset",
label = "Reset",
icon = icon("xmark")
)
),
tabPanel(
"Pick the column",
br(),
selectizeInput(
inputId = "list_columns",
label = "Choose the column:",
choices = character(0)
),
actionButton(inputId = "button2",
label = "Submit")
)
)),
mainPanel(
dataTableOutput("table"),
textOutput("text"),
plotOutput("myplot")
))
server <- function(input, output, session) {
observeEvent(input$type, {
feedbackWarning(
inputId = "type",
show = ("data2" %in% input$type),
text = "This data is... Please, be careful..."
)
})
mydata <- reactiveVal(NULL)
observe({
if (input$type == "data1") {
mydata(mtcars)
} else if (input$type == "data2") {
mydata(iris)
} else {
mydata(data.frame())
}
}) %>% bindEvent(input$button2)
observeEvent(input$reset, {
mydata(data.frame())
})
# This is to generate the choices (gene list) depending on the user's input.
observeEvent(input$button, {
updateSelectizeInput(
session = session,
inputId = "list_columns",
choices = colnames(trees),
options = list(maxOptions = length(colnames(trees))),
server = TRUE
)
})
output$table <- renderDataTable({
req(input$button2)
mydata()
})
output$text <- renderText({
req(input$button2)
input$list_columns
})
output$myplot <- renderPlot({
req(input$button2, input$button)
hist(trees[, input$list_columns])
})
}
shinyApp(ui, server)
This code gives me one tab. I would like to be able to add more tabs to it to make some plots, use the aggregate function may be. I tired to add a second tabPanel( object inside my tabsetPanel( but did not work.
I will be obliged if someone could help me with this
library(shiny)
library(dplyr)
ui <- fluidPage(
tabsetPanel(
tabPanel("Table", fluid = TRUE,
sidebarLayout(position = "left",
sidebarPanel("sidebar panel",
selectInput(inputId = "table",
label = "Choose a Supplier",
"Names"),
actionButton(inputId = "btn",label="Update")
),
mainPanel("main panel",
tableOutput("myTable")
)))
))
server <- function(input, output,session)
{
GlassSupplier <- c('Supplier 1','Supplier 2','Supplier 1','Supplier 4','Supplier 2')
WindowType <- c('Wood','Vinyl','Aluminum','Aluminum','Vinyl')
BreakageRate <- c(7.22,6.33,3.63,2,6)
df<- data.frame(GlassSupplier,WindowType,BreakageRate)
data <- eventReactive(input$btn, {
req(input$table)
df %>% dplyr::filter(GlassSupplier %in% input$table) %>%
group_by(WindowType) %>%
dplyr::summarise(BrkRate = mean(BreakageRate))
})
#Update SelectInput Dynamically
observe({
updateSelectInput(session, "table", choices = df$GlassSupplier)
})
output$myTable = renderTable({
data()
})
}
shinyApp(ui,server)
Think of tabsetPanel as any other slider/button, you can insert it inside the sidebar, in the main panel, or before the sidebarLayout.
code for ui:
u <- shinyUI(fluidPage(
titlePanel("title panel"),
sidebarLayout(position = "left",
sidebarPanel("sidebar panel",
selectInput(inputId = "table",
label = "Choose a Supplier",
"Names"),
actionButton(inputId = "btn",label="See Table"),
checkboxInput("donum1", "Make #1 plot", value = T),
checkboxInput("donum2", "Make #2 plot", value = F),
checkboxInput("donum3", "Make #3 plot", value = F),
checkboxInput("donum4", "Make #4 plot", value = F),
sliderInput("wt1","Weight 1",min=1,max=10,value=1),
sliderInput("wt2","Weight 2",min=1,max=10,value=1),
sliderInput("wt3","Weight 3",min=1,max=10,value=1),
sliderInput("wt4","Weight 4",min=1,max=10,value=1)
),
mainPanel("main panel",
tabsetPanel(
tabPanel("Plot", column(6,plotOutput(outputId="plotgraph", width="500px",height="400px"))),
tabPanel('Table', tableOutput("myTable")))
))))
How do I add a loader page while my UI populates with computations on my dataset inside the server function? My UI populates with values in about 30 secs. So I want this loader page to show for 30 secs and then hide it to show my actual UI which would have filled up by then.
Any help would be appreciated. Here's the sample code below:
ui <- fluidPage(
useShinyjs(),
div(
id = "loading_page",
h1("Loading...")
),
titlePanel("XYZ"),
sidebarLayout(
sidebarPanel(
p("Lorem Ipsum"),
selectInput(inputId = "ab", label = "SelectSomething", choices = c("A","B","C","D")),
p("Please Wait for 30 secs for data to load.."),
sliderInput(inputId = "Age", label = "Age Range", min=16, max=45, value=c(16,45)),
actionButton(inputId = "update", label = "Go!")
),
mainPanel(
h3("ABC:"),
uiOutput("table"),
br(),
uiOutput("OP1"),
br(),
uiOutput("OP2"),
uiOutput("OP3"),
br(),
uiOutput("OP4")
)
)
)
dataset<-readRDS(file = "my_data.rds")
server <- function(input, output, session) {
})
It appears that you are using code from https://stackoverflow.com/a/35665217/3358272, which makes this a dupe of sorts, but perhaps not in the vein of: how to do that with more UI components.
Just wrap all of your title and sidepanel stuff in hidden(div(...)) with an id.
From there, you can allow other things to do some work by using a reactive observe block that fires twice: the first time it sets a wake-up alarm (3000 milliseconds here), the second time it removes the #loading_page div.
ui <- fluidPage(
useShinyjs(),
div(
id = "loading_page",
h1("Loading...")
),
hidden(
div(
id = "main_content",
titlePanel("XYZ"),
sidebarLayout(
sidebarPanel(
p("Lorem Ipsum"),
selectInput(inputId = "ab", label = "SelectSomething", choices = c("A","B","C","D")),
p("Please Wait for 30 secs for data to load.."),
sliderInput(inputId = "Age", label = "Age Range", min=16, max=45, value=c(16,45)),
actionButton(inputId = "update", label = "Go!"),
),
mainPanel(
h3("ABC:"),
uiOutput("table"),
br(),
uiOutput("OP1"),
br(),
uiOutput("OP2"),
uiOutput("OP3"),
br(),
uiOutput("OP4")
)
)
)
)
)
server <- function(input, output, session) {
already_started <- FALSE
observe({
if (already_started) {
removeUI("#loading_page")
} else {
invalidateLater(3000, session)
already_started <<- TRUE
}
})
}
It would also be "right" to use a reactiveVal for already_started. The reason I didn't was that we don't need reactivity from it, just a two-shot memory.
I have the following code:
library(shiny)
vec <- seq(1,10)
ui <- fluidPage(
titlePanel(""),
sidebarLayout(
sidebarPanel(
fluidRow(
selectInput("selection", "Select number", vec, multiple = TRUE),
actionButton("First_fives", "First Fives" ),
actionButton("Last_fives", "Last Fives"),
actionButton("ok", "OK"))
),
mainPanel(
fluidRow(
h5("Selected numbers:")),
textOutput('num')
)
)
)
server <- function(input, output, session) {
observeEvent(input$First_fives,{
updateSelectInput(session, inputId = "selection", choices = vec[1:5])
})
observeEvent(input$Last_fives,{
updateSelectInput(session, inputId = "selection", choices = vec[6:10])
})
data <- reactiveValues()
observeEvent(input$ok,{
data$selected <- input$city
})
output$num <- renderText({data$selected})
}
shinyApp(ui = ui, server = server)
I almost managed to do what I want but not quite.
My selectInput box is empty when running the code and you can select amongst 10 items (from 1 to 10). This is fine.
Now I would like, when clicking on the button "First fives", the numbers 1 to 5 to be added to this empty box. In others words I would like to get the same as on the picture below in one click.
Please add selected on the updateSelectInput. The code will be like this:
observeEvent(input$First_fives,{
updateSelectInput(session, inputId = "selection", choices = vec[1:5],selected = vec[1:5])
})
observeEvent(input$Last_fives,{
updateSelectInput(session, inputId = "selection", choices = vec[6:10],selected = vec[6:10])
})
Please not I have only checked this function,not others.
Pls check if this meet your requirements.
I have been working with the Shiny package, there is one function, which the user is able to select from a list of choices, based on the choice, the plot will update. however, right now the app does not update when the selection changes.
server.R
----------
library(shiny)
library(quantmod)
library(TTR)
shinyServer(function(input, output, session) {
selectedsymbol <- reactive({
symbol <- input$selectstock
})
output$stockplotoverview <- renderPlot({
symbolinput <- selectedsymbol()
getSymbols(symbolinput)
chartSeries(get(symbolinput))
addMACD()
addBBands()
})
output$candlechart <- renderPlot({
symbolinput <- input$selectstock
getSymbols(symbolinput)
candleChart(get(symbolinput),multi.col=TRUE,theme="white")
})
output$barchart <- renderPlot({
symbolinput <- input$selectstock
getSymbols(symbolinput)
barChart(get(symbolinput))
})
})
ui.R
library(shiny)
shinyUI(fluidPage(
# Application title
titlePanel("Hello Shiny!"),
# Sidebar component
sidebarLayout(
sidebarPanel(
selectInput("selectstockset", label = h3("Select the stock set"), choices = list("My Stock set" = 1,
"Good Stock Set" = 2,
"Customize" = 3), selected = 1),
selectInput("selectalgo", label = h3("Select the algorithm"), choices = list("Worst Increment" = 1,
"PAMR" = 2,
"SMA" = 3), selected = 1),
dateRangeInput("daterange", label = h3("Date Range")),
submitButton("Simulate")
),
# Show a plot of the generated distribution
mainPanel(
tabsetPanel(
tabPanel("Stock Set",
helpText("Select a stock to examine.
Information will be collected from yahoo finance."),
textInput("stocksetname", label = h4("Stock Set Name"),
value = "Enter text...") ,
# uiOutput("selectstock"),
selectInput("selectstock", label = h4("Select the stock"), choices = list("AAPL" = "AAPL",
"SBUX" = "SBUX",
"GS" = "GS")),
tabsetPanel(
tabPanel("Overview",
plotOutput("stockplotoverview")
),
tabPanel("Candle Chart",
plotOutput("candlechart")
),
tabPanel("Bar Chart",
plotOutput("barchart"))
),
hr(),
fluidRow(
column(3,
actionButton("addtostockset","Add to stock set"),
tags$style(type='text/css', "#addtostockset { align: right;}")
),
column(3,
actionButton("confirm","Confirm stock set"),
tags$style(type='text/css', "#confirm { align: right; }")
)
)),
tabPanel("Simulation Window"),
tabPanel("Statistical Result")
)
)
)))
Nothing is returned by your reactive conductor:
selectedsymbol <- reactive({
symbol <- input$selectstock
})
Use
selectedsymbol <- reactive({
symbol <- input$selectstock
return(symbol)
})