Add a button next to statement in shiny - r

I am trying to display text in Shiny. But I also need to add a button next to the displayed text.
When when I open the application I can see the plain HTML content (but no button)
Shiny code:
library(shiny)
ui <- fluidPage(
headerPanel("Example reactiveValues"),
mainPanel(
# input field
textInput("user_text", label = "Enter some text:", placeholder = "Please enter some text."),
actionButton("submit", label = "Submit"),
# display text output
textOutput("text"))
)
server <- function(input, output) {
flag_1 <- TRUE
text_reactive = reactiveValues(text = "No values are updated")
output$text <- renderText({
text_reactive$text
})
observeEvent(input$submit,{
if(flag_1 <- FALSE)
{
text_reactive$text <- input$user_text
}
else {
text_reactive$text <- paste0("hi", HTML(as.character(actionButton('id','label'))))
}
})
}
shinyApp(ui = ui, server = server)
Is there a way to render the HTML code into an actual button?

How about the following?
library(shiny)
ui <- fluidPage(
headerPanel("Example reactiveValues"),
mainPanel(
# input field
textInput("user_text", label = "Enter some text:", placeholder = "Please enter some text."),
actionButton("submit", label = "Submit"),
# display text output
uiOutput("text"))
)
server <- function(input, output) {
flag_1 <- TRUE
text_reactive = reactiveValues(text = "No values are updated")
output$text <- renderUI({
HTML(text_reactive$text)
})
observeEvent(input$submit,{
if(flag_1 <- FALSE)
{
text_reactive$text <- input$user_text
}
else {
text_reactive$text <- paste0("hi", HTML(as.character(actionButton('id',input$user_text))))
}
})
}
shinyApp(ui = ui, server = server)

Related

Shiny: Update a reactive value with textInput() in modalDialog()

I Want to update a Value based on a textInput() within an modalDialog(). I found this answer which does work, but it uses reactiveValues() which creates problems in my case further down in my code.
Is there a way to to update my value text through textInput() and modalDialog() without the use of reactiveValues()?
This works
library(shiny)
library(shinyWidgets)
if (interactive()) {
shinyApp(
ui <- fluidPage(
actionBttn("reset", "RESET", style="simple", size="sm", color = "warning"),
verbatimTextOutput(outputId = "text")
),
server = function(input, output, session) {
l <- reactiveValues()
observeEvent(input$reset, {
# display a modal dialog with a header, textinput and action buttons
showModal(modalDialog(
tags$h2('Please enter your personal information'),
textInput('name', 'Name'),
textInput('state', 'State'),
footer=tagList(
actionButton('submit', 'Submit'),
modalButton('cancel')
)
))
})
# only store the information if the user clicks submit
observeEvent(input$submit, {
removeModal()
l$name <- input$name
l$state <- input$state
})
# display whatever is listed in l
output$text <- renderPrint({
if (is.null(l$name)) return(NULL)
paste('Name:', l$name, 'and state:', l$state)
})
}
)
}
This does not work
It fails to update the value l when I dont use the l <- reactiveValues().
library(shiny)
library(shinyWidgets)
if (interactive()) {
shinyApp(
ui <- fluidPage(
actionBttn("reset", "RESET", style="simple", size="sm", color = "warning"),
verbatimTextOutput(outputId = "text")
),
server = function(input, output, session) {
l <- NULL
observeEvent(input$reset, {
# display a modal dialog with a header, textinput and action buttons
showModal(modalDialog(
tags$h2('Please enter your personal information'),
textInput('name', 'Name'),
footer=tagList(
actionButton('submit', 'Submit'),
modalButton('cancel')
)
))
})
# only store the information if the user clicks submit
observeEvent(input$submit, {
removeModal()
l <- input$name
})
# display whatever is listed in l
output$text <- renderPrint({
if (is.null(l)) return(NULL)
paste('Name:', l)
})
}
)
}
renderPrint needs a reactive dependency to be invalidated and re-rendered. Accordingly using a non-reactive variable in this scenario isn't making any sense.
You should rather work on the downstream problems.
Here is another approach using eventReactive:
library(shiny)
library(shinyWidgets)
ui <- fluidPage(
br(),
actionBttn("reset", "RESET", style="simple", size="sm", color = "warning"),
verbatimTextOutput(outputId = "text")
)
server <- function(input, output, session) {
observeEvent(input$reset, {
# display a modal dialog with a header, textinput and action buttons
showModal(modalDialog(
tags$h2('Please enter your personal information'),
textInput('name', 'Name'),
footer=tagList(
actionButton('submit', 'Submit'),
modalButton('cancel')
)
))
})
# only store the information if the user clicks submit
submittedName <- eventReactive(input$submit, {
removeModal()
input$name
})
output$text <- renderPrint({
req(submittedName())
paste('Name:', submittedName())
})
}
shinyApp(ui, server)
Edit: using reactiveVal for the placeholder:
library(shiny)
library(shinyWidgets)
ui <- fluidPage(
br(),
actionBttn("reset", "RESET", style="simple", size="sm", color = "warning"),
verbatimTextOutput(outputId = "text")
)
server <- function(input, output, session) {
observeEvent(input$reset, {
# display a modal dialog with a header, textinput and action buttons
showModal(modalDialog(
tags$h2('Please enter your personal information'),
textInput('name', 'Name'),
footer=tagList(
actionButton('submit', 'Submit'),
modalButton('cancel')
)
))
})
submittedName <- reactiveVal("placeholder")
# only store the information if the user clicks submit
observeEvent(input$submit, {
removeModal()
submittedName(input$name)
})
output$text <- renderPrint({
paste('Name:', submittedName())
})
}
shinyApp(ui, server)

How to have a user input text and create a list with shiny? R

I have the following app which allows for text to be entered and it is then saved as VALUE and printed on a panel.
Although it looks like I can only do this with one text input at a time - even if I click add (so I don't believe this button is working). On top of that I would like for the user to be able to add multiple inputs (like I have below).
And then my VALUE function should be list with multiple inputs.
code below
library(shiny)
ui <- fluidPage(
headerPanel("R Package App"),
sidebarPanel(
# selectInput("options", "options", choices=c('abc','def')),
textInput("textbox", "Enter R Package Name", ""),
actionButton("add","Add")
),
mainPanel(
textOutput("caption")
)
)
server <- function(input, output, session) {
observe({
VALUE <- ''
if(input$add>0) {
isolate({
VALUE <- input$textbox
})
}
updateTextInput(session, inputId = "textbox", value = VALUE)
})
output$caption <- renderText({
input$textbox
})
}
shinyApp(ui = ui, server = server)
Have you considered using selectizeInput with it's create option?
library(shiny)
packagesDF <- as.data.frame(installed.packages())
ui <- fluidPage(
headerPanel("R Package App"),
sidebarPanel(
selectizeInput(
inputId = "selectedPackages",
label = "Enter R Package Name",
choices = packagesDF$Package,
selected = NULL,
multiple = TRUE,
width = "100%",
options = list(
'plugins' = list('remove_button'),
'create' = TRUE,
'persist' = TRUE
)
)
),
mainPanel(textOutput("caption"))
)
server <- function(input, output, session) {
output$caption <- renderText({
paste0(input$selectedPackages, collapse = ", ")
})
}
shinyApp(ui = ui, server = server)

R Shiny: Cylce the class of an actionButton on click

I'd like to have an actionButton that cycles its class between "btn-success", "btn-warning", "btn-danger" based on the button click. Unfortunately I can't seem to figure out how to get that value into the class argument of the actionButton.
library(shiny)
v <- reactiveValues(btn_status = "btn-secondary")
ui <- fluidPage(
# Application title
titlePanel("Change Button Color on click"),
# Create an action button that cycles through 3 bootstrap colors and can be reset
mainPanel(
actionButton("run","L", class = isolate(v$btn_status)),
actionButton("reset", "Clear"),
textOutput("status"),
)
)
server <- function(input, output) {
observeEvent(input$run, {
v$btn_status <- "btn-success"
})
observeEvent(input$reset, {
v$btn_status <- "NULL"
})
output$status <- renderText({
v$btn_status
})
}
shinyApp(ui = ui, server = server)
It's not entirely clear to me what you're trying to do (see my comment above); but I think you're after something like this:
library(shiny)
valid_status <- c("btn-success", "btn-warning", "btn-danger")
ui <- fluidPage(
titlePanel("Change Button Color on click"),
mainPanel(
uiOutput("statusButton"),
actionButton("reset", "Clear"),
textOutput("status"),
)
)
server <- function(input, output, session) {
v <- reactiveValues(button_idx = 1)
get_button_idx <- reactive(v$button_idx)
output$statusButton <- renderUI({
idx <- get_button_idx()
actionButton("run", "L", class = valid_status[idx])
})
observeEvent(input$run, {
v$button_idx <- ifelse(v$button_idx < 3, v$button_idx + 1, 1)
})
observeEvent(input$reset, {
v$button_idx <- 1
})
output$status <- renderText({
valid_status[v$button_idx]
})
}
shinyApp(ui = ui, server = server)
producing
The key is to use a reactive value within renderUI to update the class of the actionButton. To align the buttons you could use fluidRow if necessary.

How to update a character vector from shiny textInput?

I want to add the input text to a vector in a Shiny app every time a button is clicked. This is the example I'm working with:
library(shiny)
ui <- fluidPage(
textInput(inputId = "inquiry", label = "enter text"),
actionButton(inputId = "searchButton", label = "Run"),
verbatimTextOutput("queryList", placeholder = FALSE)
)
server <- function(input, output, session) {
queryList <- c()
observeEvent(input$searchButton, {
queryList[length(queryList)+1] <- input$inquiry
output$queryList <- renderPrint({
queryList
})
})
}
shinyApp(ui = ui, server = server)
So if "item1" is entered and the button is clicked, then "item2" is entered and the button is clicked again, queryList should look like c("item1", "item2"), but it seems to just be replacing "item1" with "item2". I'm sure I'm missing something very simple...queryList[length(queryList)+1] looks a little strange, but it works in a non-reactive environment.
Making queryList reactive fixed it for me:
library(shiny)
ui <- fluidPage(
textInput(inputId = "inquiry", label = "enter text"),
actionButton(inputId = "searchButton", label = "Run"),
verbatimTextOutput("queryList", placeholder = FALSE)
)
server <- function(input, output, session) {
queryList <- reactiveValues()
queryList$values <- c()
observeEvent(input$searchButton, {
queryList$values[length(queryList$values) + 1] <- input$inquiry
})
output$queryList <- renderPrint({
if (!is.null(queryList$values)) {
queryList$values
}
})
}
shinyApp(ui = ui, server = server)

Dynamic number of actionButtons tied to unique observeEvent

I'd like to generate a dynamic number of actionButtons, and then have each generated button print its number to the console. This is my best attempt so far, but I still can't get the observeEvent for each of the first 10 buttons to recognize the button clicks. How do I tie the buttons to an observeEvent?
library(shiny)
ui <- basicPage(
fluidRow(
actionButton(inputId = "add_button",
label = "Add Button")
),
uiOutput("more_buttons")
)
server <- function(input, output){
rvs <- reactiveValues(buttons = list(actionButton(inputId = "button1",
label = 1)))
observeEvent(eventExpr = input$add_button,
handlerExpr = {
len <- length(rvs$buttons) + 1
rvs$buttons[[len]] <- actionButton(inputId = paste0("button",len),
label = len)
})
output$more_buttons <- renderUI({
do.call(fluidRow, rvs$buttons)
})
# This is the part that doesn't work
for(ii in 1:10){
observeEvent(eventExpr = input[[paste0("button",ii)]],
handlerExpr = print(ii))
}
}
shinyApp(ui, server)
Your really close, just wrap the observeEvent part in local.
library(shiny)
ui <- basicPage(
fluidRow(
actionButton(inputId = "add_button",
label = "Add Button")
),
uiOutput("more_buttons")
)
server <- function(input, output){
rvs <- reactiveValues(buttons = list(actionButton(inputId = "button1",
label = 1)))
observeEvent(eventExpr = input$add_button,
handlerExpr = {
len <- length(rvs$buttons) + 1
rvs$buttons[[len]] <- actionButton(inputId = paste0("button",len),
label = len)
})
output$more_buttons <- renderUI({
do.call(fluidRow, rvs$buttons)
})
observeEvent(rvs$buttons,{
for(ii in 1:length(rvs$buttons)){
local({
i <- ii
observeEvent(eventExpr = input[[paste0("button",i)]],
handlerExpr = {print(sprintf("You clicked btn number %d",i))})
})
}
})
}
shinyApp(ui, server)
Let the inputIds of the buttons to follow a pattern like "button1", "button2", "button3", use regex to isolate those inputIds from the 'input' object in the observeEvent trigger, and convert the result to a list:
observeEvent(
lapply(
names(input)[grep("button[0-9]+",names(input))],
function(name){
input[[name]]
}
),
{
code to run when any button with inputId matching the regex is pressed
}
)

Resources