Have pickerInput dropdown placed in front of confirmSweetAlert Buttons - r

I'm trying to get the pickerInput dropdown placed in front of the confirmSweetAlert buttons, but using z-index within CSS doesn't appear to work. Any other suggestions?
library(shiny)
library(shinyWidgets)
ui <- fluidPage(
actionButton(
inputId = "launch",
label = "Launch Confirm!"
)
)
server <- function(input, output, session) {
# Launch sweet alert confirmation
observeEvent(input$launch, {
confirmSweetAlert(
session = session,
inputId = "test",
title = "This is a Test!",
type = "info",
text = tags$div(
div(style="position: relative; z-index: 1;", pickerInput(
inputId = "numbers",
multiple = TRUE,
choices = 1:5,
width = "100%"
)),
closeOnClickOutside = FALSE,
html = TRUE
))
})
}
if (interactive())
shinyApp(ui, server)

You can use options = pickerOptions(container = "body") in pickerInput to append the select to a specific element, in that case "body" help positioning the menu.
Full example:
library(shiny)
library(shinyWidgets)
ui <- fluidPage(
actionButton(
inputId = "launch",
label = "Launch Confirm!"
)
)
server <- function(input, output, session) {
# Launch sweet alert confirmation
observeEvent(input$launch, {
confirmSweetAlert(
session = session,
inputId = "test",
title = "This is a Test!",
type = "info",
text = tags$div(
pickerInput(
inputId = "numbers",
multiple = TRUE,
choices = 1:5,
width = "100%",
options = pickerOptions(container = "body")
),
closeOnClickOutside = FALSE,
html = TRUE
))
})
}
if (interactive())
shinyApp(ui, server)

Related

How do I use input from `selectizeInput` to filter a list of options and then `updateSelectizeInput`?

BACKGROUND:
I have a large list of stock symbols, 27,000 rows, that I would like to be choices in a selectizeInput() on a shinyApp. Since the list is large I am using server = T in updateSelectizeInput().
AIM:
I would like the options list to not load/render until a user starts typing a string into selectizeInput(), so that I can return all symbols that start with that letter, to reduce loading all 27,000 rows in the input. I would like input$ticker to be what is observed and then what triggers the filtering code logic. How can i achieve this without using a specific button?
Shown below is
intended output, but with a button to produce the behavior instead of the user being in the text box. This is along the lines of what I would like, but does not automatically start searchign when I type in the box and has bad code smell to me.
current logic, using input$ticker in an observer to trigger selection of df and populate updateSelectize() with new choices, but is failing and the app is evaluating too soon?\
trying to load choices once, using upload button only doesn't work
REPREX:
1.
library(shiny)
tickers <- rep(rownames(mtcars), 850)
ui <- {
renderUI(
shiny::fluidRow(
bs4Dash::box(
title = shiny::selectizeInput(
inputId = "ticker",
label = "Ticker:",
choices = NULL,
selected = "AAPL",
options = list(
placeholder = "e.g AAPL",
create = TRUE,
maxOptions = 50L
)
),
actionButton(
inputId = "update",
label = "UPDATE NOW"
),
id = "tickerBox",
closable = F,
maximizable = F,
width = 12,
height = "250px",
solidHeader = FALSE,
collapsible = F
)
)
)
}
server <- function(input, output, session){
choice <- reactive(
tickers[startsWith(tickers$symbol, input$ticker), ]
)
observeEvent(input$update, {
updateSelectizeInput(
session = session,
label = "Ticker:",
inputId ="ticker",
choices = choice(),
server = TRUE
)
})
}
shiny::shinyApp(ui = ui, server = server)
# REPREX for selectize, glitches and `input$ticker` observer causes loop gltich?
library(shiny)
tickers <- rep(rownames(mtcars), 850)
ui <- {
renderUI(
shiny::fluidRow(
bs4Dash::box(
title = shiny::selectizeInput(
inputId = "ticker",
label = "Ticker:",
choices = NULL,
selected = "AAPL",
options = list(
placeholder = "e.g AAPL",
create = TRUE,
maxOptions = 50L
)
),
actionButton(
inputId = "update",
label = "UPDATE NOW"
),
id = "tickerBox",
closable = F,
maximizable = F,
width = 12,
height = "250px",
solidHeader = FALSE,
collapsible = F
)
)
)
}
server <- function(input, output, session){
# updateSelectizeInput(
# session = session,
# label = "Ticker:",
# inputId ="ticker",
# choices = tickers,
# server = TRUE
# )
observeEvent(input$ticker, {
choices <- tickers[startsWith(tickers$symbol, input$ticker), ]
updateSelectizeInput(
session = session,
label = "Ticker:",
inputId ="ticker",
choices = choices,
server = TRUE
)
})
}
shiny::shinyApp(ui = ui, server = server)
# REPREX for selectize
library(shiny)
tickers <- rep(rownames(mtcars), 850)
ui <- {
renderUI(
shiny::fluidRow(
bs4Dash::box(
title = shiny::selectizeInput(
inputId = "ticker",
label = "Ticker:",
choices = NULL,
selected = "AAPL",
options = list(
placeholder = "e.g AAPL",
create = TRUE,
maxOptions = 50L
)
),
actionButton(
inputId = "update",
label = "UPDATE NOW"
),
id = "tickerBox",
closable = F,
maximizable = F,
width = 12,
height = "250px",
solidHeader = FALSE,
collapsible = F
)
)
)
}
server <- function(input, output, session){
# One call to try and load ticker df
observeEvent(input$update, {
updateSelectizeInput(
session = session,
label = "Ticker:",
inputId ="ticker",
choices = ticker,
server = TRUE
)
})
}
shiny::shinyApp(ui = ui, server = server)
SEE SIMILAR POSTS:
SO POST 1, SO POST 2, SO POST 3
What do you think about something like this?
library(shiny)
tickers <- rep(rownames(mtcars), 850)
ui <- fluidPage(
tags$head(
tags$script(
HTML(
'document.addEventListener("keydown", function(e) {
Shiny.setInputValue("key_pressed", e.key);
})'
)
)
),
fluidRow(
column(2, selectizeInput("select", "Select", choices = "")),
column(1, actionButton("btn", "Search"))
)
)
server <- function(input, output, session) {
observeEvent(input$btn, {
req(input$key_pressed)
updateSelectizeInput(session, "select", choices = tickers[startsWith(tickers, input$key_pressed)], server = TRUE)
})
}
shinyApp(ui, server)
Basically I think it is not possible to just use the words which are putted to the selectInput and we need separate input. I think that selectInput is truthy (isTruthy()) only after some option was chosen (and it can't be "" of course), so we can't use anything which is putted as a word to the selectInput box before some option is actually chosen. I'm not sure, but if I'm right, it is necessary to have separate input for what you want.
However, if we could assume that:
User will use only one letter to get the options to choose
Then we can use "keydown" event (keydown). Now the user doesn't need to put anything to the selectInput box, she/he can just use a key in the keyboards, like C (letter size does matter here, because we are using startsWith()) and then push "Search" button (but of course this letter can still be put to the selectInput box to mimic what you tried to achieve). We could even imagine solution without the button, but I'm afraid in most use-cases it will be not recommended, I mean if user can interact with the app using keyboard not only to choose the options, but also for other purposes, then we would recompute new options everytime user uses key in the keyboard for - well - nothing.
Turns out that selectizeInput doesn't accept a df and must be an atomic vector. When I used tickers[[1]], the issue seemed to be solved, and the list would no longer flash.

Is there a way to create a "?" icon action button for r shiny?

I was wondering if there is a way to create a "?" icon button that when clicked it shows a pop up message explaining why behind my model. Also how would I make it horizontally inline with with my numericInput widget.
fileInput("file1", "Choose CSV File",
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")
),
helper(shiny_tag, icon = "question-circle", colour = NULL,
type = "markdown", title = "Help", content = "Content", size= "m",
buttonLabel = "Okay", easyClose = TRUE, fade = FALSE)
The second solution I have tried was also giving me issues as well.
actionButton("show", "Show modal dialog"),
server <- function(input, output) {
observeEvent(input$show, {
showModal(modalDialog(
title = "Somewhat important message",
"This is a somewhat important message.",
easyClose = TRUE,
footer = NULL
))
})
}
Try this:
library(shiny)
ui <- fluidPage(
div(
class = "input-group",
tags$span(
style = "display: inline-block",
numericInput("a", "Some number", 0, width = "100%")
),
tags$span(
style = "vertical-align: bottom;",
actionButton("b", "", icon = icon("question"))
)
)
)
server <- function(input, output, session) {
observeEvent(input$b, {
showModal(modalDialog(
title = "Somewhat important message",
"This is a somewhat important message.",
easyClose = TRUE,
footer = NULL
))
})
}
shinyApp(ui, server)

Reactivity and Renders doesn't work when switching to another tabPanel

I have a reproducible example below where only the first tabPanel is working, however when I switch to another panel, I don't get any renders (the toggle becomes un-interactable also). I have looked into conditionalPanel however I see them getting done without the use of mainPanel I was wondering if it possible to have tabs where each tab has its own mainPanel , so I can see a different sidebar and an output contained within different tabs. Any help is welcome!
options(scipen = 99999) #converts the sci numbers to their regular format
library(shiny)
library(shinyjs)
library(shinyWidgets)
library(shinyalert)
library(esquisse)
library(DT)
library(dplyr)
#library(devtools)
#library(remotes)
#remotes::install_github("dreamRs/esquisse")
library(hrbrthemes)
library(ggthemes)
library(ggplot2)
library(svglite)
ui <- fluidPage(
shinyjs::useShinyjs(), # enables javascript/jQuery enhanchments
# Create Right Side Text
navbarPage(
title= div(HTML("G<em>T</em>")),
#General reports
tabPanel("General Reports",
shinyWidgets::materialSwitch(inputId = "toggleSidebar", label = "Toggle Panel: ",
value = TRUE, status = "warning"),
sidebarLayout(
# radio/action buttons
sidebarPanel(
id = "Sidebar",
shinyWidgets::prettyRadioButtons(
inputId = "controller",
label = "Choose:",
choices = c("About"= 1,
"iris"= 2),
icon= icon("check"),
selected = 1,
status = "success",
animation="smooth"
),
br(),
br(),
a(actionButton(inputId = "admin_email", label = "Contact",
icon = icon("envelope", lib = "font-awesome")),
href="mailto:xyz#email.us")
),
#panel where output is shown from server
mainPanel(
id = "main_panel",
tabsetPanel(
id = "hidden_tabs",
type = "hidden",
tabPanelBody(
"panel1", "Text coming soon."
),
tabPanelBody(
"panel2",
tabsetPanel(
tabPanel("Data", DT::DTOutput('panel2_data')),
tabPanel(
"DIY Plot",
esquisse::esquisse_ui(
id = "esquisse2",
header = FALSE,
container = esquisseContainer(
width = "100%", height = "760px", fixed = FALSE
),
controls = c("labs", "parameters", "appearance", "filters", "code")
)
)
)
)
)
)
)
),
# monthly reports
tabPanel("Extra General Reports",
shinyWidgets::materialSwitch(inputId = "toggleSidebar", label = "Toggle Panel: ",
value = TRUE, status = "warning"),
sidebarLayout(
# radio/action buttons
sidebarPanel(
id = "Sidebar",
shinyWidgets::prettyRadioButtons(
inputId = "controller",
label = "Choose:",
choices = c("About"= 3,
"mtcars"= 4),
icon= icon("check"),
selected = 3,
status = "success",
animation="smooth"
),
br(),
br(),
a(actionButton(inputId = "admin_email", label = "Contact",
icon = icon("envelope", lib = "font-awesome")),
href="mailto:xyz#email.us")
),
#panel where output is shown from server
mainPanel(
id = "main_panel",
tabsetPanel(
id = "hidden_tabs",
type = "hidden",
tabPanelBody(
"panel3", "Text coming soon."
),
tabPanelBody(
"panel4",
tabsetPanel(
tabPanel("Data", DT::DTOutput('panel4_data')),
tabPanel(
"DIY Plot",
esquisse::esquisse_ui(
id = "esquisse4",
header = FALSE,
container = esquisseContainer(
width = "100%", height = "760px", fixed = FALSE
),
controls = c("labs", "parameters", "appearance", "filters", "code")
)
)
)
)
)
)
)
),
#resizes the navbar tabs/button
tags$head(tags$style(HTML('.navbar-brand {width: 270px; font-size:35px; text-align:left;
font-family: "serif";')))
)
)
server <- function(input, output, session) {
# this event hides the side panel when toggled on/off
observeEvent(input$toggleSidebar, {
shinyjs::toggle(id = "Sidebar", condition = input$toggleSidebar)
if(!isTRUE(input$toggleSidebar)) {
shinyjs::runjs("$('#main_panel').removeClass('col-sm-8').addClass('col-sm-12')")
} else {
shinyjs::runjs("$('#main_panel').removeClass('col-sm-12').addClass('col-sm-8')")
}
})
# here we put all the data
data_sets <- list(df1 = data.frame(),
df2 = iris,
df3 = data.frame(),
df4 = mtcars)
# store current dataset in reactive so we can work with plot panels
data_to_use <- reactiveValues(name = "df", data = data.frame())
# modules only need to be called it once but individually for esquisse
esquisse::esquisse_server(id = "esquisse2", data_rv = data_to_use)
esquisse::esquisse_server(id = "esquisse4", data_rv = data_to_use)
observeEvent(input$controller, {
# skip first panel since it is used to display navigation
updateTabsetPanel(session, inputId= "hidden_tabs", selected = paste0("panel", input$controller))
# enswure value is avilable throught selected tabSet
req(input$controller)
# get current data and df name
data_to_use$data <- data_sets[[as.numeric(input$controller)]]
data_to_use$name <- names(data_sets[as.numeric(input$controller)])
# update table and sum. Use server = FALSE to get full table
output[[paste0('panel', input$controller, '_data')]] <- DT::renderDT(server = FALSE, {
DT::datatable(data_to_use$data,
filter = 'top',
extensions = 'Buttons')})
})
}
#runs the app
shinyApp(ui= ui, server= server)
You have two radioButtons, one for each sidebar, but both of them have the inputId = "controller". Same with inputId = "toggleSidebar". InputIds need to be unique in shiny!
I suggest you either use a single sidebar for the entire app, or since both tabs are essentially identical you can also use modules.

How to render centralized text inputs in a window and save then? Customer Registration Example

Well i trying to open a window by pressing a button to write some text inputs and submit to MySql table, like this example below, but i dont know how i centralize the texts inputs.
ATTEMPT
library(shinyWidgets)
library(shiny)
library(shinyjs)
library(RMariaDB)
shinyApp(
ui = fluidPage(
useShinyjs(), # Set up shinyjs
actionButton("btn", "Costumer Registration"),
),
server = function(input, output,session) {
#connect to MySQL
#localuserpassword= "PASSW"
#myconnect <- dbConnect(RMariaDB::MariaDB(), user='user', password=localuserpassword, dbname='name', host='localhost')
observeEvent(input$btn, { # open a window by pressing the "btn" button
confirmSweetAlert(
btn_labels = c("Cancel","Submit"),
session = session,
inputId = "SubmitCostumertoSQL",
type = "info",
title = paste0("Customer Registration"),
danger_mode = F,
closeOnClickOutside = T,
showCloseButton =T,
text = tags$div(
renderUI(textInput("name", "Name")),
renderUI(textInput("NRLE", "National Registry of Legal Entities")),
renderUI(textInput("address", "Address")),
)
)
} )
observeEvent(input$SubmitCostumertoSQL, {
#Send to MySQL
#querycostumer= paste("insert into TABLENAME(Name,NRLE,Addres)
# values('",input$name,"','",
# input$NRLE,"','",
# input$address,
# "')" ,sep = '')
#dbSendQuery(myconnect,querycostumer)
})
}
)
How to centralize the text input and save then into a object?
Include align = 'center' in your div, e.g. text = tags$div(align = 'center',
textInput can also include placeholder text if you want to match the example more closely.
Minimal working example
library(shinyWidgets)
library(shiny)
library(shinyjs)
shinyApp(
ui = fluidPage(
useShinyjs(),
actionButton("btn", "Costumer Registration"),
),
server = function(input, output,session) {
observeEvent(input$btn, {
confirmSweetAlert(
btn_labels = c("Cancel","Submit"),
session = session,
inputId = "SubmitCostumertoSQL",
type = "info",
title = paste0("Customer Registration"),
danger_mode = F,
closeOnClickOutside = T,
showCloseButton =T,
text = tags$div(align = 'center',
renderUI(textInput("name", "Name")),
renderUI(textInput("NRLE", "National Registry of Legal Entities")),
renderUI(textInput("address", "Address")),
)
)
})
})

Disabling Confirm Button in confirmSweetAlert

I'm trying to disable the confirm button in confirmSweetAlert unless selectizeInput has some input within it. There seem to be solutions by using Javascript, such as swal.disableConfirmButton() and document.getElementsByClassName().disabled = true, but when I run them under shinyjs::runjs, these don't seem to work. Are there any solutions out there to resolve this issue? Here's my sample code:
shinyApp(
ui <- fluidPage(
actionButton("button", "Show Sweet Alert!")
),
server <- function(input, output, session) {
observeEvent(input$button, {
confirmSweetAlert(
session = session,
inputId = "letterSelect",
title = "Select a Letter!",
type = "info",
text = tags$div(
h4("Please select from the options below then press 'Confirm'.", align = "center"),
selectizeInput(
inputId = "letters",
label = NULL,
choices = c("A", "B", "C"),
options = list(placeholder = "None selected."),
multiple = TRUE,
width = '100%')
),
closeOnClickOutside = FALSE
)
})
}
)
This seems to work:
library(shiny)
library(shinyWidgets)
library(shinyjs)
shinyApp(
ui <- fluidPage(
useShinyjs(),
actionButton("button", "Show Sweet Alert!")
),
server <- function(input, output, session) {
observeEvent(input$button, {
confirmSweetAlert(
session = session,
inputId = "letterSelect",
title = "Select a Letter!",
type = "info",
text = tags$div(
h4("Please select from the options below then press 'Confirm'.", align = "center"),
selectizeInput(
inputId = "letters",
label = NULL,
choices = c("A", "B", "C"),
options = list(placeholder = "None selected."),
multiple = TRUE,
width = '100%')
),
closeOnClickOutside = FALSE
)
runjs("Swal.getConfirmButton().setAttribute('disabled', '');")
})
observe({
if(is.null(input$letters)){
runjs("Swal.getConfirmButton().setAttribute('disabled', '');")
}else{
runjs("Swal.getConfirmButton().removeAttribute('disabled');")
}
})
}
)

Resources