R shiny - Disable/enable single radio button based upon select input - r

I want to disable "3" when "B" is selected and move radio button selection to "1". When "A" is selected again, I want "3" to be enable again. I tried a couple of things with shinyjs::runjs("") but it didn't work out in desirable way. Any help will be appreciated.
library(shiny)
library(shinyjs)
library(shinyWidgets)
if (interactive()) {
ui <- fluidPage(
useShinyjs(),
selectInput(inputId="input",
label="choose ",
c("A" = "a",
"B" = "b")),
radioButtons(inputId="select",
label="number",
c("1"="one",
"2"="two",
"3"="three")),
mainPanel(verbatimTextOutput("output")
)
)
server <- function(input, output) {
observeEvent(input$input, {
if(input$input=="b"){
# disable 3
shinyjs::runjs("")
}else{
# enable 3 again if input$input=="a"
}
})
output$output <- renderText({ input$select })
}
shinyApp(ui, server)
}

One way to do it is use conditionPanel. Try this.
library(shiny)
library(shinyjs)
library(shinyWidgets)
ui <- fluidPage(
useShinyjs(),
selectInput(inputId="input",
label="choose ",
c("A" = "a",
"B" = "b")),
conditionalPanel(condition = "input.input == 'a'",
radioButtons(inputId="select",
label="number",
c("1"="one",
"2"="two",
"3"="three"),
selected="three")
),
conditionalPanel(condition = "input.input == 'b'",
radioButtons(inputId="select2",
label="number",
c("1"="one",
"2"="two"),
selected="one")
),
mainPanel(verbatimTextOutput("output")
)
)
server <- function(input, output) {
mysel <- reactive({
if (input$input=="a") {
sel <- input$select
} else{
sel <- input$select2
}
sel
})
output$output <- renderText({ mysel() })
}
shinyApp(ui, server)
Another way is to use updateRadioButtons.
ui <- fluidPage(
useShinyjs(),
selectInput(inputId="input",
label="choose ",
c("A" = "a",
"B" = "b")),
radioButtons(inputId="select",
label="number",
c("1"="one",
"2"="two",
"3"="three"),
selected="one"),
mainPanel(verbatimTextOutput("output")
)
)
server <- function(input, output, session) {
observeEvent(input$input, {
if(input$input=="b"){
mychoices <- c("1"="one", "2"="two")
}else{
mychoices <- c("1"="one", "2"="two", "3"="three")
}
updateRadioButtons(session, "select", choices = mychoices)
})
output$output <- renderText({ input$select })
}
shinyApp(ui, server)

Related

Hide text input and button after click

I am new with Shiny. I have developed a very simple app that modifies a string inserted in a text input after the click of a button. The result appears in a text output present from the beginning. This is my code:
# ui.R
library(shiny)
library(shinyjs)
ui <- fluidPage(
useShinyjs(),
textInput("caption", "Caption", "abc"),
actionButton("btn_input", "Enter"),
verbatimTextOutput("value")
)
# server.R
library(shiny)
library(shinyjs)
server <- function(input, output) {
output$value <- reactive({
# toggle(id="caption")
input$btn_input
v <- isolate({input$caption})
if (v == "xxx") {
value <- paste(v, "a")
} else {
value <- paste(v, "b")
}
value
})
}
I would like the text output to appear only after clicking the button.
At the same time I would like the caption, the text input and the button to disappear after clicking the button.
What is the easiest way to make this change? Thanks in advance.
I think conditionalPanel is the easiest way:
library(shiny)
ui <- fluidPage(
conditionalPanel(
"input.btn_input === 0",
textInput("caption", "Caption", "abc"),
actionButton("btn_input", "Enter")
),
conditionalPanel(
"input.btn_input !== 0",
style = "display: none;",
verbatimTextOutput("value")
)
)
server <- function(input, output) {
Value <- eventReactive(input$btn_input, {
v <- input$caption
if (v == "xxx") {
paste(v, "a")
} else {
paste(v, "b")
}
})
output$value <- renderPrint({
Value()
})
}
shinyApp(ui, server)
If you want a "Back" button, as asked in your comment, you can proceed as follows:
library(shiny)
ui <- fluidPage(
conditionalPanel(
"output.show_input",
textInput("caption", "Caption", "abc"),
actionButton("btn_input", "Enter")
),
conditionalPanel(
"output.show_output",
style = "display: none;",
verbatimTextOutput("value"),
actionButton("btn_back", "Back")
)
)
server <- function(input, output) {
ShowInput <- reactiveVal(TRUE)
output$show_input <- reactive({
ShowInput()
})
outputOptions(output, "show_input", suspendWhenHidden = FALSE)
ShowOutput <- reactiveVal(FALSE)
output$show_output <- reactive({
ShowOutput()
})
outputOptions(output, "show_output", suspendWhenHidden = FALSE)
observeEvent(input$btn_input, {
ShowInput(FALSE)
ShowOutput(TRUE)
})
observeEvent(input$btn_back, {
ShowInput(TRUE)
ShowOutput(FALSE)
})
Value <- eventReactive(input$btn_input, {
v <- input$caption
if (v == "xxx") {
paste(v, "a")
} else {
paste(v, "b")
}
})
output$value <- renderPrint({
Value()
})
}
shinyApp(ui, server)
...
# output$value <- reactive({
output$value <- eventReactive(input$btn_input, {
...

Shiny, two action buttons, it only responds to the second button and not to the first button

Tell me in R Shiny, there are two action buttons. I want to update the data according to the button I press. But for some reason it only responds to the second button and not to the first button. What is the solution?
if (interactive()) {
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
actionButton("action_1", "Get 1"),
actionButton("action_2", "Get 2"),
),
mainPanel(
textOutput("result")
),
)
)
server <- function(input, output) {
data <- eventReactive(input$action_1, 1)
data <- eventReactive(input$action_2, 2)
output$result <- renderText(data())
}
shinyApp(ui, server)
}
The second line of this piece of code overwrites the first one:
data <- eventReactive(input$action_1, 1)
data <- eventReactive(input$action_2, 2)
You can do:
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
actionButton("action_1", "Get 1"),
actionButton("action_2", "Get 2"),
),
mainPanel(
textOutput("result")
),
)
)
server <- function(input, output) {
result <- reactiveVal()
observeEvent(input$action_1, { result(1) })
observeEvent(input$action_2, { result(2) })
output$result <- renderText(result())
}
shinyApp(ui, server)
}
If you have many buttons you can simply add a class to it and some simple JS to monitor the last click like so:
library(shiny)
monitorJS <- "$(document).on('click', '.monitor', function () {
Shiny.onInputChange('last_click',this.id);
});"
ui <- fluidPage(
tags$head(tags$script(monitorJS)),
sidebarLayout(
sidebarPanel(
uiOutput("buttons")
),
mainPanel(
textOutput("result")
),
)
)
server <- function(input, output, session) {
output$buttons <- renderUI({
a <- list()
for(i in 1:200){
id <- paste0("action_",i)
name <- paste0("Get ",i)
a[[i]] <- actionButton(id, name, class = "monitor")
}
tagList(a)
})
data <- eventReactive(input$last_click,{
# Your click ligic here
value <- gsub("action_","",input$last_click)
value
})
output$result <- renderText({
data()
})
}
shinyApp(ui, server)

Is there a R function to apply in filter option in R shiny

I have the below code. I need to put a main filter in mainpanel so that i can select the categories that in turn should change the numbers (summary)
# faithful is the dataset
# Iris is the dataset
iris$New <- ifelse(iris$Sepal.Width>2.5,"greater than 2.5","Not Greater
than 2.5")
library(shiny)
sample1 <- 1:3
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput(
"x",
"Operations",
choices = c("summary","stem","typeof","mode","birth"),
multiple = TRUE,
selectize = TRUE
)
),
mainPanel(
h6("Here it is"),
verbatimTextOutput("message")
)
)
)
server <- function(input, output, session) {
output$message <- renderPrint({
if(input$x == "summary"){
summary(iris$Petal.Width)
} else if (input$x == "stem"){
print(stem(faithful$eruptions))
} else if (input$x == "typeof"){
typeof(sample1)
} else if (input$x == "mode"){
mode(sample1)
}
})
}
shinyApp(ui, server)
Can I have a main filter of "Species" from Iris dataset. When I select "setosa",the summary should change accordingly
If we need to change the summary based on the values of 'Species', use renderUI with uiOutput
sample1 <- 1:3
library(shiny)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(selectInput("x","Operations",choices =
c("summary","stem","typeof","mode","birth"),
multiple=FALSE,selectize = TRUE)),
mainPanel(h6("Here it is"),
verbatimTextOutput("message"),
uiOutput("Species")
)
)
)
server <- function(input, output, session) {
r1 <- reactive({
if(input$x == "summary")
{
summary(iris$Petal.Width[iris$Species == input$Species])
} else if (input$x == "stem")
{
print(stem(faithful$eruptions))
} else if (input$x == "typeof")
{
typeof(sample1)
} else if (input$x == "mode")
{
mode(sample1)
}
})
output$message <- renderPrint({r1()})
output$Species <- renderUI({
selectInput("Species", "species",
choices = as.character(unique(iris$Species)), multiple = FALSE)
})
}
shinyApp(ui, server)
-output

Using data from one shiny module to another shiny module

I am trying to use a value from one shiny module and pass it to a second shiny module to print it. So when user select orange from first dropdown it show print you have selected orange. But as of now it prints you have selected ATC which is nothing but the id I am passing . Below is the code I am using.Thank you.
library(shiny)
library(shinydashboard)
library(shinyWidgets)
dropDownUI <- function(id, div_width = "col-xs-12 col-md-8") {
ns <- NS(id)
div(column(3, uiOutput(ns("class_level"))),
column(3,uiOutput(ns("selected_product_ui"))
))
}
chartTableBoxUI <- function(id, div_width = "col-xs-12 col-md-8") {
ns <- NS(id)
div(tabBox(width = 12, title = id,
tabPanel(icon("bar-chart"),
textOutput(ns("selected_var")))
)
)
}
chartTableBox <- function(input, output, session, data,ImProxy) {
output$selected_var <- renderText({
ns <- session$ns
paste("You have selected",ns(ImProxy$selected_class))
})
}
dropDown <- function(input, output, session) {
ns <- session$ns
observe({output$class_level <- renderUI({
selectInput(
ns("selected_class"),
label = h4("Classification Level"),
choices = list(
"apple " = "apple",
"orange " = "orange"),
selected = "orange"
)})
})
a<-reactive({input$selected_class})
output$selected_product_ui <- renderUI({
req(input$selected_class)
Sys.sleep(0.2)
ns <- session$ns
if (input$selected_class == "apple") {
my_choices <- c("foo","zoo","boo")
} else if (input$selected_class == "orange") {
my_choices <- c("22","33","44")
} else {
my_choices <- c("aa","bb","cc")
}
selectInput(inputId = ns("selected_product"),
label = h4("Product Family"),
choices = my_choices)
})
}
sidebar <- dashboardSidebar(sidebarMenu(
menuItem("aaa",tabName = "aaa"),
menuItem("bbb", tabName = "bbb"),
menuItem("ccc", tabName = "ccc")
))
body <- ## Body content
dashboardBody(tabItems(
tabItem(tabName = "aaa",
fluidRow(dropDownUI(id = "dropdown"),
fluidRow(chartTableBoxUI(id = "ATC"))
)
)))
# Put them together into a dashboardPage
ui <- dashboardPage(
dashboardHeader(title = "Loyalty Monthly Scorecard"),
sidebar,
body
)
server = {
shinyServer(function(input, output, session) {
callModule(dropDown, id = "dropdown")
callModule(chartTableBox, id = "ATC", data = MyData)
})
}
shinyApp(ui = ui, server = server)
I tried the solution from this question Passing data within Shiny Modules from Module 1 to Module 2 using reactive values and observer event aargument "ImProxy" is missing, with no default
There are two issues with your code:
ImProxy is a user defined variable. You have not defined it, nor have you passed it as an argument.
You are using the id as the title of your tabBox.
Both are corrected below.
library(shiny)
library(shinydashboard)
library(shinyWidgets)
dropDownUI <- function(id, div_width = "col-xs-12 col-md-8") {
ns <- NS(id)
div(column(3,uiOutput(ns("class_level"))),
column(3,uiOutput(ns("selected_product_ui"))
))
}
chartTableBoxUI <- function(id, div_width = "col-xs-12 col-md-8") {
ns <- NS(id)
div(tabBox(width = 12, title = textOutput(ns("title_var")), ## fixing issue 2
tabPanel(icon("bar-chart"),
textOutput(ns("selected_var")))
)
)
}
chartTableBox <- function(input, output, session, data,a) { ## fixing issue 1
output$selected_var <- renderText({
paste("You have selected",a())
})
output$title_var <- renderText({ a() }) ## fixing issue 2
}
dropDown <- function(input, output, session) {
ns <- session$ns
observe({output$class_level <- renderUI({
selectInput(
ns("selected_class"),
label = h4("Classification Level"),
choices = list(
"apple " = "apple",
"orange " = "orange"),
selected = "orange"
)})
})
a<-reactive({input$selected_class})
output$selected_product_ui <- renderUI({
req(input$selected_class)
Sys.sleep(0.2)
ns <- session$ns
if (input$selected_class == "apple") {
my_choices <- c("foo","zoo","boo")
} else if (input$selected_class == "orange") {
my_choices <- c("22","33","44")
} else {
my_choices <- c("aa","bb","cc")
}
selectInput(inputId = ns("selected_product"),
label = h4("Product Family"),
choices = my_choices)
})
return(a) ## fixing issue 1
}
# Put them together into a dashboardPage
ui = dashboardPage(
dashboardHeader(title = "Loyalty Monthly Scorecard"),
dashboardSidebar(sidebarMenu(
menuItem("aaa",tabName = "aaa")
)),
dashboardBody(tabItems(
tabItem(tabName = "aaa",
fluidRow(dropDownUI(id = "dropdown"),
chartTableBoxUI(id = "ATC") # this text
)
)))
)
server = {
shinyServer(function(input, output, session) {
a = callModule(dropDown, id = "dropdown")
callModule(chartTableBox, id = "ATC", data = MyData, a = a)
})
}
shinyApp(ui = ui, server = server)

updateSelectizeInput in a shiny module

I would like to use a reactive value to load control a selectizeInput widget. I can do this with a simple shiny app, but I can't seem to be able to replicate it when I try to reorganize it in a module.
In the following code I have a simple app with an input widget and a button. After pressing the button, I want the selectizeInput() widget to be updated with the values stored in the reactive variable.
library(shiny)
# GLOBAL VAR TO BE LOADED after pressing the button
# -------------
STORED <- reactiveValues(choices = c("a", "b", "c")
, selected = c("c"))
# UI
# -------------
ui <- fixedPage(
wellPanel(
# input widget
selectInput("widget1"
, "label"
,choices = c("WRONG A","WRONG B","WRONG C")
,selected="WRONG A"
)
# update button
, actionButton("plotBtn"
, "update"
, class = "btn-primary")
)
)
# SERVER
# -------------
server <- function(input, output, session) {
observeEvent(input$plotBtn,{
message("update button was pressed")
updateSelectInput(session
,"widget1"
,choices = STORED$choices
, selected = STORED$selected
)
})
}
# APP
shinyApp(ui, server)
after pressing the button, the widget is correctly updated with "c" selected, and the choices are correctly imported. However, when I try to write it as a shiny module, the button doesn't work.
library(shiny)
# INIT VARS TO BE LOADED AFTER PRESSING THE BUTTON
# ------------------------------------------------------------------------------
STORED <- reactiveValues(choices = c("a", "b", "c")
, selected = c("c"))
# MODULE SELECTIZEINPUT
# ------------------------------------------------------------------------------
input_widgetUI <- function(id) {
ns <- NS(id)
selectizeInput(ns("input_widget")
, label = "label"
, choices = c("WRONG A","WRONG B","WRONG C")
, selected = "WRONG A"
)
}
# MODULE BUTTON
# ------------------------------------------------------------------------------
plotBtnUI <- function(id){
ns <- NS(id)
fluidPage(actionButton(ns("plotBtn"), "update", class = "btn-primary"))
}
plotBtn <- function(input, output, session) {
ns <- session$ns
print("Loading plotBtn()")
observeEvent(input$plotBtn, {
message("update button was pressed")
updateSelectizeInput(session
, ns("widget1")
, choices = STORED$choices
, selected= STORED$selected
)
})
}
# #############################################################################
# SHINY APP
# #############################################################################
ui <- fixedPage(
wellPanel(
input_widgetUI("widget1")
, plotBtnUI("button")
)
)
server <- function(input, output, session) {
callModule(plotBtn, "button")
}
shinyApp(ui, server)
I belive I might be using the wrong ID. Any suggestion is very welcome! Thanks
you want to have the selectizeInput and actionButton in the same UI function. otherwise will you have different namespaces for each of them. In this case you also don't need the ns function in the server part. You only need that when you are rendering dynamic UI objects
Here is working version of your code
STORED <- reactiveValues(choices = c("a", "b", "c")
, selected = c("c"))
# MODULE SELECTIZEINPUT
# ------------------------------------------------------------------------------
input_widgetUI <- function(id) {
ns <- NS(id)
tagList(
selectizeInput(ns("input_widget")
, label = "label"
, choices = c("WRONG A","WRONG B","WRONG C")
, selected = "WRONG A"
),
actionButton(ns("plotBtn"), "update", class = "btn-primary")
)
}
plotBtn <- function(input, output, session) {
ns <- session$ns
print("Loading plotBtn()")
observeEvent(input$plotBtn, {
message("update button was pressed")
updateSelectizeInput(session = getDefaultReactiveDomain()
, inputId = "input_widget"
, choices = STORED$choices
, selected= STORED$selected
)
})
}
# #############################################################################
# SHINY APP
# #############################################################################
ui <- fixedPage(
wellPanel(
input_widgetUI("widget1")
)
)
server <- function(input, output, session) {
callModule(plotBtn, "widget1")
}
shinyApp(ui, server)
This solution is closer to what I was looking for. It still allows to keep the button and the input widget in distinct modules (i.e. have the button on a different tab for example).
library(shiny)
options(shiny.reactlog=TRUE)
# INIT GLOBAL VARS
# --------------------------------------------------------------------
STORED <- reactiveValues(choices = c("WRONG A","WRONG B","WRONG C")
, selected = "WRONG A")
# MODULE SELECTIZEINPUT
#----------------------------------------------------------------------
input_widgetUI <- function(id) {
ns <- NS(id)
tagList(
selectizeInput(ns("input_widget")
, label = "label"
, choices = NULL
, selected = NULL
)
)
}
input_widgetSERVER <- function(input, output, session){
#ns <- session$ns
observe({
updateSelectizeInput(session
, "input_widget"
, choices = STORED$choices
, selected= STORED$selected
, server=TRUE
)
})
}
# MODULE BUTTON
# ---------------------------------------------------------------------
plotBtnUI <- function(id){
ns <- NS(id)
fluidPage(actionButton(ns("plotBtn"), "update", class = "btn-primary"))
}
plotBtnSERVER <- function(input, output, session) {
#ns <- session$ns
print("Loading plotBtn()")
observeEvent(input$plotBtn, {
message("update button was pressed")
# VARS TO BE LOADED AFTER PRESSING THE BUTTON
STORED$choices <- c("a", "b", "c")
STORED$selected <- c("c")
})
}
# ######################################################################
# SHINY APP
# ######################################################################
ui <- fixedPage(
tagList(
input_widgetUI("widget1")
, plotBtnUI("button")
)
)
server <- function(input, output, session) {
callModule(input_widgetSERVER, "widget1")
callModule(plotBtnSERVER, "button")
}
# launch the app
shinyApp(ui, server)

Resources