I have two inputs to be removed from the ui.R
fileInput(inputId = "FileInput",label = "Choose a csv file",accept = '.csv'),
uiOutput("SKU")
Inside server i am using an observeEvent to remove these 2 inputs and insert one. Though the insertUi is working I am not able to remove the other 2.
PFB the code:
observeEvent(input$Save,{
removeUI(
selector = "div:has(> #FileInput)"
)
insertUI(
selector = "#Save",
where = "afterEnd",
ui =fluidPage(
tags$hr(),
fluidRow(column(offset=0,1,actionButton("clean","Start cleaning the Data")))
)
)
})
It seems you have to treat it the same way in which the shiny blog example treats text by wrapping it in a div with id.
tags$div(
fileInput(inputId = "FileInput",label = "Choose a csv file",accept = '.csv'),
id='FileInput'
)
Example
ui <- fluidPage(
mainPanel(
tags$div(fileInput('element1','Input file...'),id='element1'),
actionButton('remove','Remove File Input')
)
)
server <- function(input, output) {
observeEvent(input$remove,{
removeUI(selector = '#element1')
})
}
shinyApp(ui = ui, server = server)
Related
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)
Below I have an R Shiny code to upload an input file to the application. All csv files that'll be uploaded will have a column 'carname'. I want to have a dropdown that's able to access and select choices in that column. How do I access the uploaded file in the ui?
Error: Error in data$carname : object of type 'closure' is not subsettable
ui <- fluidPage(
headerPanel("Webpapp"),
sidebarPanel(
fileInput(inputId = "filedata",
label = "Upload the Raw Data File",
accept = c("text/csv", "text/comma-separated-values,text/plain",
".csv")),
selectInput("cars", "Select car:", choices = data$carname, selected = "Nissan Sentra"),
),
mainPanel(
plotOutput('plot'),
)
)
# Define server code ####
server <- function(input, output) {
data <- reactive({
req(input$filedata)
read.csv(input$filedata$datapath, skip = 15, header = F)
})
output$plot <- renderPlot({
if (is.null(data())) {
return(NULL)
}
plot_probe(input$cars) #Plotting function in global
})
}
shinyApp(ui = ui, server = server)
This is not necessary and also I would say not recommend in this case to use renderUI. updateSelectInput() will be faster (Make R Shiny Dashboards Faster with updateInput, CSS, and JavaScript) and require less rewriting of code:
library(shiny)
ui <- fluidPage(
headerPanel("Webpapp"),
sidebarPanel(
fileInput(inputId = "filedata",
label = "Upload the Raw Data File",
accept = c("text/csv", "text/comma-separated-values,text/plain",
".csv")),
selectInput("cars", "Select car:", choices = "", selected = "Nissan Sentra"),
),
mainPanel(
plotOutput('plot'),
)
)
# Define server code ####
server <- function(session, input, output) {
data <- reactive({
req(input$filedata)
read.csv(input$filedata$datapath, skip = 15, header = F)
})
observe({
req(data())
updateSelectInput(session, "cars", choices = data()$carname)
})
output$plot <- renderPlot({
if (is.null(data())) {
return(NULL)
}
plot_probe(input$cars) #Plotting function in global
})
}
shinyApp(ui = ui, server = server)
What I have changed:
In UI part I passed "" to the choice argument in selectInput, because as #gdevaux mentioned, you cannot use in this way data from server in UI.
I have added session parameter to server function - it is necessary for update* functions.
I have added updateSelectInput() inside observer - it will update selectInput if data() won't be NULL.
As #gdevaux did, I have changed your choices = data$carname into choices = data()$carname. It is because data as a reactive you need to use as a function.
You cannot access the uploaded file from the UI.
But you can create an UI element from the server, and send it to the UI with the functions renderUI and UIOutput.
ui <- fluidPage(
headerPanel("Webpapp"),
sidebarPanel(
fileInput(inputId = "filedata",
label = "Upload the Raw Data File",
accept = c("text/csv", "text/comma-separated-values,text/plain",
".csv")),
uiOutput("ui_select")
),
mainPanel(
plotOutput('plot'),
)
)
# Define server code ####
server <- function(input, output) {
data <- reactive({
req(input$filedata)
read.csv(input$filedata$datapath, skip = 15, header = F)
})
# UI element for select input
output$ui_select <- renderUI({
req(data())
selectInput("cars", "Select car:", choices = data()$carname, selected = "Nissan Sentra")
})
output$plot <- renderPlot({
if (is.null(data())) {
return(NULL)
}
plot_probe(input$cars) #Plotting function in global
})
}
shinyApp(ui = ui, server = server)
Need Help, I would like to upload an image file display it on shiny and the image can be remove.
I already tried but the problem is first attemp upload file is OK but second attemp is the image are not displayed.
library(shiny)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
fluidRow(
fileInput("myFile", "Choose a file", accept = c('image/png', 'image/jpeg')),
actionButton('reset', 'Reset Input')
)
),
mainPanel(
div(id = "image-container", style = "display:flexbox")
)
)
)
server <- function(input, output) {
observeEvent(input$myFile, {
inFile <- input$myFile
if (is.null(inFile))
return()
b64 <- base64enc::dataURI(file = inFile$datapath, mime = "image/png")
insertUI(
selector = "#image-container",
where = "afterBegin",
ui = img(src = b64, width = 600, height = 600)
)
})
observeEvent(input$reset, {
removeUI(
selector = "#image-container",
)
})
}
shinyApp(ui = ui, server = server)
Any solution is really appreciated
With your removeUI you are removing the container. Remove its content instead:
observeEvent(input$reset, {
removeUI(
selector = "#image-container > *"
)
})
I have a shiny app with a button which calls a modal dialog where a UI should be inserted. I'm using insertUI because I want to add UI elements dynamically. The problem is, whenever I press the action button, the app crashes with the following error message:
Warning: Error in as.character: cannot coerce type 'closure' to vector of type 'character'
[No stack trace available]
If I set immediate = T in the insertUI() then there is no error, but also no UI inserted. Can someone explain what's going on here? Here's a reprex.
library(shiny)
ui <- fluidPage(
actionButton("add", "addConstraints")
)
server <- function(input, output, session) {
observeEvent(input$add, {
showModal(modalDialog(
selectizeInput(session$ns("constraintType"), label = "Select constraint type", choices = c("Comparison", "Numeric", "Interval")),
tags$div(id = session$ns("constraintPlaceholder")),
insertUI(
selector = paste0("#", session$ns("constraintPlaceholder")),
where = "afterEnd",
ui = HTML("test")
),
title = "Set Constraints",
footer = tagList(
modalButton("Cancel"),
actionButton(session$ns("confirmConstraint"), "Add")
)
))
})
}
shinyApp(ui, server)
insertUI needs to be called outside modalDialog. What inside modalDialog is UI components, they should be shinyTags, or HTML elements. insertUI is a server call, it can't be added to modalDialog
library(shiny)
ui <- fluidPage(
actionButton("add", "addConstraints")
)
server <- function(input, output, session) {
observeEvent(input$add, {
showModal(modalDialog(
selectizeInput(session$ns("constraintType"), label = "Select constraint type", choices = c("Comparison", "Numeric", "Interval")),
tags$div(id = session$ns("constraintPlaceholder")),
title = "Set Constraints",
footer = tagList(
modalButton("Cancel"),
actionButton(session$ns("confirmConstraint"), "Add")
)
))
insertUI(
selector = paste0("#", session$ns("constraintPlaceholder")),
where = "afterEnd",
ui = HTML("test")
)
})
}
shinyApp(ui, server)
I created a module to help me accept 1)an excel file 2)a text input for the sheet name and 3) a text input for the range.
I want to be able to use this module in an App such that each time I click on the action button (AddExcelDataButton in the code below), it allows me to input a different file. I also need to be able to extract the contents of the file later.
I tried the below code in the main App, but it is throwing me the following errors
error1: The UI is linking all the inputs "inside the button"
error2: I am unable to figure out how to "access" or retrieve the filenames later in the code.
Any help in doing this the right way is highly appreciated please!
CODE FOR THE MODULE:
importExceldataUI <- function(importExceldata){
tagList(
tags$div(
HTML(paste0("<b>", "Enter Your Data Here"))
),
tags$div(
fileInput(inputId = "ImportExcelFile",
label = "Excel File",
multiple=FALSE),
style = "display:inline-block; vertical-align:top"
),# end of tags$div for fileInput ImportExcelFile
tags$div(
textInput(inputId = "ExcelSheetName",
label = "Sheet",
value="Data",),
style = "display:inline-block; vertical-align:top"
),#end of tags$Div for texinput-ExcelSheetName
tags$div(
textInput(inputId = "ExcelSheetRange",
label = "Range",
value = "C5:BN1000"),
style = "display:inline-block"
)#end of tags$div for textInput - sheetrange
)
}
importExceldataServer <- function(importExceldata){
moduleServer(importExceldata, function(input, output, session){
})
}
CODE FOR MAIN APP
importExceldataApp <- function(){
ui <- fluidPage(
mainPanel(
actionButton(inputId = "AddExcelDataButton", label = "Click here to add Excel Data"),
)#emd pf mainpanel
)
server <- function(input, output, session){
observeEvent(input$AddExcelDataButton, {
insertUI(selector = "#AddExcelDataButton",
ui = importExceldataUI(paste0("file",input$AddExcelDataButton)))
})#end of observeEvent
}
shinyApp(ui, server)
}
importExceldataApp()
There are some errors you need to fix:
to use modules, you must have IDs for both UI and server. For each pair, they must have the same ID.
For ids in module UI, you must use namespace NS.
For insertUI, default is insert into the selector, apparently, you don't want to insert inside a button, you need to add after the button, so you need have where argument, please read the help file of this function.
You should read more about shiny modules standards
Here is the working code:
library(shiny)
importExceldataUI <- function(id){
ns <- NS(id)
tagList(
tags$div(
HTML(paste0("<b>", "Enter Your Data Here"))
),
tags$div(
fileInput(inputId = ns("ImportExcelFile"),
label = "Excel File",
multiple=FALSE),
style = "display:inline-block; vertical-align:top"
),# end of tags$div for fileInput ImportExcelFile
tags$div(
textInput(inputId = ns("ExcelSheetName"),
label = "Sheet",
value="Data"),
style = "display:inline-block; vertical-align:top"
),#end of tags$Div for texinput-ExcelSheetName
tags$div(
textInput(inputId = ns("ExcelSheetRange"),
label = "Range",
value = "C5:BN1000"),
style = "display:inline-block"
)#end of tags$div for textInput - sheetrange
)
}
importExceldataServer <- function(id){
moduleServer(id, function(input, output, session){
observeEvent(input$ImportExcelFile, {
req(input$ImportExcelFile)
print(input$ImportExcelFile$datapath)
})
})
}
importExceldataApp <- function(){
ui <- fluidPage(
mainPanel(
actionButton(inputId = "AddExcelDataButton", label = "Click here to add Excel Data"),
)#emd pf mainpanel
)
server <- function(input, output, session){
observeEvent(input$AddExcelDataButton, {
insertUI(selector = "#AddExcelDataButton", where = "afterEnd",
ui = importExceldataUI(paste0("file",input$AddExcelDataButton)))
importExceldataServer(paste0("file",input$AddExcelDataButton))
})#end of observeEvent
}
shinyApp(ui, server)
}
importExceldataApp()
So to read the path of uploaded file, just use input$ImportExcelFile$datapath, datapath is the file location. Here in my code, I just print it out, you can do other things.