Hiding or showing shiny elements without pressing submit - r

I have a shiny app where i want to hide or show some elements based on user input. This i tried to do by using conditionalPanel in shiny. However, it works only after pressing the submit button. I want to hide or show the textInput element without pressing the submit button. Below is an example what I tried.
UI.R
library(shiny)
shinyUI(fluidPage(
titlePanel("submitButton example"),
fluidRow(
column(3, wellPanel(
sliderInput("n", "N:", min = 10, max = 1000, value = 200,
step = 10),
checkboxInput("checkbox", label = "Message", value = FALSE),
conditionalPanel(
condition = "input.checkbox == true",
textInput("text", "Text:", "text here")),
submitButton("Submit")
)),
column(6,
plotOutput("plot1", width = 400, height = 300),
verbatimTextOutput("text")
)
)
))
Server.R
shinyServer(function(input, output) {
output$plot1 <- renderPlot({
hist(rnorm(input$n))
})
output$text <- renderText({
paste("Input text is:", input$text)
})
})
I want to show the textInput as soon as user checks the checkbox and hide it on uncheck without any dependency on submit button.

You can try
UI:
library(shiny)
shinyUI(fluidPage(
titlePanel("submitButton example"),
fluidRow(
column(3, wellPanel(
sliderInput("n", "N:", min = 10, max = 1000, value = 200,
step = 10),
checkboxInput("checkbox_1", label = "Message", value = FALSE),
uiOutput('test')
,actionButton("Submit",label ="Submit" )
)),
column(6,
plotOutput("plot1", width = 400, height = 300),
verbatimTextOutput("text")
)
)
))
server:
shinyServer(function(input, output,session) {
output$test=renderUI({
if(input$checkbox_1==T){
list(textInput("text", "Text:", "text here"),
numericInput("num","num",0), numericInput("num1","num1",0))}
})
observeEvent(input$Submit,{
output$plot1 <- renderPlot({
hist(rnorm(isolate(input$n)))
})
output$text <- renderText({
paste("Input text is:", isolate(input$text))
})
})
})

Related

How can I hide\show\toggle certain fields in R shiny modal based on other modal fields

I wish to have a popout modal within a shiny app that depending on the user's action within the modal,
it would show or hide certain fields.
For example, the Modal includes a button that when pressed, another button would apear\disappear.
sadly, although the observeEvent detects a change in the hide\show button, shinyjs::toggle(), shinyjs::hide()
and shinyjs::show() fail to work
example script:
library(shiny)
ui <- fluidPage(
actionButton("show_modal", "show modal"),
)
server <- function(input, output) {
observeEvent(input$show_modal, {
showModal(
modalDialog(footer = NULL,easyClose = T,
tagList(
fluidRow(
box(status = "primary", width = 6, style = "direction: ltr",
actionButton("toggle_btn", "show or hide second button")
)),
fluidRow(
box(status = "success", width = 6, style = "direction: ltr",
actionButton("box_btn", "Box!")
))
)
))
})
observeEvent(input$toggle_btn, {
shinyjs::toggle("box_btn")
cat("\npresentation button pressed\n")
})
}
shinyApp(ui, server)
You can do it without shinyjs by using conditionalPanel():
library(shiny)
ui <- fluidPage(
actionButton("show_modal", "show modal"),
)
server <- function(input, output) {
rv <- reactiveValues(show_btn = FALSE)
observeEvent(input$toggle_btn, {
rv$show_btn <- !rv$show_btn
})
output$show_btn <- reactive({rv$show_btn})
outputOptions(output, "show_btn", suspendWhenHidden = FALSE)
observeEvent(input$show_modal, {
# add_path_to_existing_offers_DB(user = user)
showModal(
modalDialog(
footer = NULL,
easyClose = T,
tagList(
fluidRow(
actionButton("toggle_btn", "show or hide second button")
),
conditionalPanel(
condition = "output.show_btn == true",
fluidRow(
actionButton("box_btn", "Box!")
)
)
)
)
)
})
}
shinyApp(ui, server)
Turns out as Dean Attali the author of shinyjs pointed out kindly,
that I failed to call useShinyjs() function.
library(shiny)
library(shinyjs)
ui <- fluidPage(
**useShinyjs(),**
actionButton("show_modal", "show modal"),
)
server <- function(input, output) {
observeEvent(input$show_modal, {
showModal(
modalDialog(footer = NULL,easyClose = T,
tagList(
fluidRow(
box(status = "primary", width = 6, style = "direction: ltr",
actionButton("toggle_btn", "show or hide second button")
)),
fluidRow(
box(status = "success", width = 6, style = "direction: ltr",
actionButton("box_btn", "Box!")
))
)
))
})
observeEvent(input$toggle_btn, {
shinyjs::toggle("box_btn")
cat("\npresentation button pressed\n")
})
}
shinyApp(ui, server)

Dynamic Tab creation with content

I am trying to build a shiny app where the user can decide how many tabs he wants to be shown. Here's what I have so far:
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(glue)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
sliderInput(inputId = "slider", label = NULL, min = 1, max = 5, value = 3, step = 1)
),
dashboardBody(
fluidRow(
box(width = 12,
p(
mainPanel(width = 12,
column(6,
uiOutput("reference")
),
column(6,
uiOutput("comparison")
)
)
)
)
)
)
)
server <- function(input, output) {
output$reference <- renderUI({
tabsetPanel(
tabPanel(
"Reference",
h3("Reference Content"))
)
})
output$comparison <- renderUI({
req(input$slider)
tabsetPanel(
lapply(1:input$slider, function(i) {
tabPanel(title = glue("Tab {i}"),
value = h3(glue("Content {i}"))
)
})
)
})
}
shinyApp(ui = ui, server = server)
This does not produce the desired results, as the comparison tabs are not shown properly.
I have already checked out these 2 threads:
R Shiny - add tabPanel to tabsetPanel dynamically (with the use of renderUI)
R Shiny dynamic tab number and input generation
but they don't seem to solve my problem. Yes, they create tabs dynamically with a slider, but they don't allow to fill these with content as far as I can tell.
What works for me is a combination for lapply and do.call
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(glue)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
sliderInput(inputId = "slider", label = NULL, min = 1, max = 5, value = 3, step = 1)
),
dashboardBody(
fluidRow(
box(width = 12,
p(
mainPanel(width = 12,
column(6,
uiOutput("reference")
),
column(6,
uiOutput("comparison")
)
)
)
)
)
)
)
server <- function(input, output) {
output$reference <- renderUI({
tabsetPanel(
tabPanel(
"Reference",
h3("Reference Content"))
)
})
output$comparison <- renderUI({
req(input$slider)
myTabs = lapply(1:input$slider, function(i) {
tabPanel(title = glue("Tab {i}"),
h3(glue("Content {i}"))
)
})
do.call(tabsetPanel, myTabs)
})
}
shinyApp(ui = ui, server = server)

Shiny - reset the value of the input when it is hidden?

How can I reset the value of an input when it is hidden? Or better - don't send the data to the server when it is hidden. Is it possible?
For instance:
shinyUI(pageWithSidebar(
headerPanel("Click the button"),
sidebarPanel(
radioButtons(
inputId = "switch",
label = "Select hide or show:",
choices = c(
"Show" = "show",
"Hide" = "hide"
),
selected = NULL,
inline = FALSE
),
conditionalPanel(
condition = "input.switch == 'show'",
numericInput("n", "N:", min = 0, max = 100, value = 0)
),
actionButton("goButton", "Go!")
),
mainPanel(
textOutput("text")
)
))
shinyServer(function(input, output) {
# builds a reactive expression that only invalidates
# when the value of input$goButton becomes out of date
# (i.e., when the button is pressed)
ntext <- eventReactive(input$goButton, {
input$n
})
output$text <- renderText({
ntext()
})
})
The UI still sends the data of this numericInput to the server when 'Hide' is checked and the numericInput is hidden. I don't want the UI sends the data when the input is hidden. Or - reset it to 0.
Any ideas?

r shiny: access input fields in UI

I'm trying to access an input field in mainPanel from the sidebarPanel, but I couldn't succeed.
Code:
shinyUI(pageWithSidebar{
sidebarPanel(
sliderInput("x", "X", min = 10, max = 100, value = 50)
),
mainPanel(
#this is where I wanna use the input from the sliderInput
#I tried input.x, input$x, paste(input.x)
)
})
Where seems to be the problem? Or isn't possible to use the input from the sidebarPanel in the mainPanel?
You can only use the inputs in the server side.
For example :
library(shiny)
runApp(list(
ui = pageWithSidebar(
headerPanel("test"),
sidebarPanel(
sliderInput("x", "X", min = 10, max = 100, value = 50)
),
mainPanel(
verbatimTextOutput("value")
)
),
server = function(input, output, session) {
output$value <- renderPrint({
input$x
})
}
))
EDIT ::
Dynamically set the dimensions of the plot.
Use renderUi to render a plot output using the values of your inputs.
library(shiny)
runApp(list(
ui = pageWithSidebar(
headerPanel("Test"),
sidebarPanel(
sliderInput("width", "Plot Width (%)", min = 0, max = 100, value = 100),
sliderInput("height", "Plot Height (px)", min = 0, max = 400, value = 400)
),
mainPanel(
uiOutput("ui")
)
),
server = function(input, output, session) {
output$ui <- renderUI({
plotOutput("plot", width = paste0(input$width, "%"), height = paste0(input$height, "px"))
})
output$plot <- renderPlot({
plot(1:10)
})
}
))

Shiny Reactivity

I've got an application with a large number of parameters. Each parameters has lots of granularity which make finding the desired one a pain. This causes the reactive portion to constantly calculate which slows things down. I added a submitButton which solved the above problem but then experience another problem in turn.
Below is a simple replication of the framework I build. The parameter input takes in a number from 1 to 1000, which indicates the sample to which I want. What I would like to do is be able to do above but also be able to resample with the same set of parameters. What is happening now after adding the submit button is that it renders the resample button inoperable unless I click resample first AND then update button.
Any ideas of making them both working separately?
shinyServer(function(input, output) {
getY<-reactive({
a<-input$goButton
x<-rnorm(input$num)
return(x)
})
output$temp <-renderPlot({
plot(getY())
}, height = 400, width = 400)
})
shinyUI(pageWithSidebar(
headerPanel("Example"),
sidebarPanel(
sliderInput("num",
"Number of Samples",
min = 2,
max = 1000,
value = 100),
actionButton("goButton", "Resample"),
submitButton("Update View")
),
mainPanel(
tabsetPanel(
tabPanel("Heatmap",
plotOutput("temp")
),
tabPanel("About"),
id="tabs"
)#tabsetPanel
)#mainPane;
))
EDIT based on Joe's Answer:
shinyServer(function(input, output) {
getY<-reactive({
isolate({a<-input$goButton
x<-rnorm(input$num)
return(x)})
})
output$temp <-renderPlot({
b<-input$goButton1
plot(getY())
}, height = 400, width = 400)
})
shinyUI(pageWithSidebar(
headerPanel("Example"),
sidebarPanel(
sliderInput("num",
"Number of Samples",
min = 2,
max = 1000,
value = 100),
actionButton("goButton", "Resample"),
actionButton("goButton1","Update View")
),
mainPanel(
tabsetPanel(
tabPanel("Heatmap",
plotOutput("temp")
),
tabPanel("About"),
id="tabs"
)#tabsetPanel
)#mainPane;
))
The answer was given by Joe Cheng in a comment above, but seeing that the OP had difficulty understanding it, I write it out explicitly below, for the record:
# ui.R
library("shiny")
shinyUI(
pageWithSidebar(
headerPanel("Example")
,
sidebarPanel(
sliderInput("N", "Number of Samples", min = 2, max = 1000, value = 100)
,
actionButton("action", "Resample")
)
,
mainPanel(
tabsetPanel(
tabPanel("Plot", plotOutput("plotSample"))
,
id = "tabs1"
)
)
)
)
# server.R
library("shiny")
shinyServer(
function(input, output, session) {
Data <- reactive({
input$action
isolate({
return(rnorm(input$N))
return(x)
})
})
output$plotSample <-renderPlot({
plot(Data())
} , height = 400, width = 400
)
})
Note that having input$action inside reactive(), where "action" is the actionButton's inputID, is enough to trigger a new rendering of the plot. So you need only one actionButton.
change getY so that all but the first line is wrapped in isolate({ ... })
change submitButton to actionButton
add a line inside of renderPlot to read the new actionButton

Resources