I would like to show in my shiny app a link that directs to the URL generated based on user's input. I don't want to show the full text of the URL. I know the a(href="",label="") function can be used if I know the URL beforehand, but in this case the URL depends on the user's input. The following doesn't work:
ui <- fluidPage(
titlePanel("Show map of a given state"),
sidebarLayout(
sidebarPanel(
textInput("state", label = "State", value = "CA", placeholder = "California or CA"),
actionButton("showU","Show map")
),
mainPanel(
conditionalPanel(
condition = "input.showU > 0",
htmlOutput("url"),
a(href=htmlOutput("url"),"Show in Google Map",target="_blank")
)
)
)
)
server <- function(input, output){
observeEvent(input$showU,{
output$url <-renderUI({paste("https://www.google.com/maps/place/", input$state, sep="")})
})
}
shinyApp(ui,server)
I hope I can click on the "Show in Google Map" and be directed to the URL generated on the fly. Please help me, thank you.
You need to use renderUI together with uiOutput to update UI reactively:
library(shiny)
ui <- fluidPage(
titlePanel("Show map of a given state"),
sidebarLayout(
sidebarPanel(
textInput("state", label = "State", value = "CA", placeholder = "California or CA"),
actionButton("showU","Show map")
),
mainPanel(
conditionalPanel(
condition = "input.showU > 0",
uiOutput("url")
)
)
)
)
server <- function(input, output){
observeEvent(input$showU,{
output$url <-renderUI(a(href=paste0('https://www.google.com/maps/place/', input$state),"Show in Google Map",target="_blank"))
})
}
shinyApp(ui,server)
If this questions is actually about creating reactive URL links, then HubertL's answer is the way to go.
If you want to keep the map and search funciton all self-contained in the shiny, rather than having to open a new link to Google Maps, you can use my googleway package to achieve the same task
library(shiny)
library(googleway)
ui <- fluidPage(
titlePanel("Show map of a given state"),
sidebarLayout(
sidebarPanel(
),
mainPanel(
google_mapOutput(outputId = "myMap", height = "600px")
)
)
)
server <- function(input, output){
## you need a valid API key from Google Maps
## https://developers.google.com/maps/
map_key <- "your_map_api_key"
output$myMap <- renderGoogle_map({
google_map(key = map_key, search_box = T)
})
}
shinyApp(ui,server)
I used a HTML button for which the url could be generated recursively
library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("HTML button"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30)
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot"),
HTML(paste0(htmlOutput('url_test')))
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
output$distPlot <- renderPlot({
# generate bins based on input$bins from ui.R
x <- faithful[, 2]
bins <- seq(min(x), max(x), length.out = input$bins + 1)
# draw the histogram with the specified number of bins
hist(x, breaks = bins, col = 'darkgray', border = 'white')
})
output$url_test = renderText({
paste('Go to Google')
})
cultivar_url = reactive({
print('https://www.google.com')
})
}
# Run the application
shinyApp(ui = ui, server = server)
Related
I use R shiny to create multiple tabs for the scatter plot of different variables in a single app. My code seems alright, but the error says I have not "defined my main panel."
Can someone please help where I have gone wrong, or if my whole approach is inaccurateenter code here, please let me know!
library(shiny)
library(tidyverse)
India <- read.csv("D:/R/Practice 3/Indiadata.csv")
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Deaths vs all variables "),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
selectInput("Deaths", "All variables:",
choices = c("cases"="total_cases","vaccinations"="total_vaccinations",
"people vaccinated"="people_vaccinated","people fully vaccinated"="people_fully_vaccinated",
"total booster"="total_boosters","new vaccinations"="new_vaccinations", "median age"="median_age"))
)
),
mainPanel(
tabsetPanel(type = "tabs",
tabPanel(plotOutput("plot1")),
tabPanel(plotOutput("plot2")),
tabPanel(plotOutput("plot3")),
tabPanel(plotOutput("plot4")),
tabPanel(plotOutput("plot5")),
tabPanel(plotOutput("plot6")),
tabPanel(plotOutput("plot7"))
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
output$plot1 <- renderPlot({
ggplot(India,aes(y=total_deaths,x=total_cases))
})
output$plot2 <- renderPlot({
ggplot(India,aes(y=total_deaths,x=total_vaccinations))
})
output$plot3 <- renderPlot({
ggplot(India,aes(y=total_deaths,x=people_vaccinated))
})
output$plot4 <- renderPlot({
ggplot(India,aes(y=total_deaths,x=people_fully_vaccinated))
})
output$plot5 <- renderPlot({
ggplot(India,aes(y=total_deaths,x=total_boosters))
})
output$plot6 <- renderPlot({
ggplot(India,aes(y=total_deaths,x=new_vaccinations))
})
output$plot7 <- renderPlot({
ggplot(India,aes(y=total_deaths,x=median_age))
})
}
# Run the application
shinyApp(ui = ui, server = server)
mainPanel is an argument of the sidebarLayout() function. So, you just need to move it up into the sidebarLayout() function:
ui <- fluidPage(
# Application title
titlePanel("Deaths vs all variables "),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
selectInput("Deaths", "All variables:",
choices = c("cases"="total_cases","vaccinations"="total_vaccinations",
"people vaccinated"="people_vaccinated","people fully vaccinated"="people_fully_vaccinated",
"total booster"="total_boosters","new vaccinations"="new_vaccinations", "median age"="median_age"))
),
mainPanel(
tabsetPanel(type = "tabs",
tabPanel(plotOutput("plot1")),
tabPanel(plotOutput("plot2")),
tabPanel(plotOutput("plot3")),
tabPanel(plotOutput("plot4")),
tabPanel(plotOutput("plot5")),
tabPanel(plotOutput("plot6")),
tabPanel(plotOutput("plot7"))
)
)
)
)
I am building a shiny application that should have different options for different user categories. Therefore, I have different subfiles where the inputs are definied and the dependent on the role the respective file is loaded via the source command.
It works, however, the source command always prints a TRUE on my shiny app. I can't get rid of it no matter what option of the source command I am trying.
Here a screenshot of the problem
And a minimal example: app.R
library(shiny)
library(ggplot2)
# Define UI for app that draws a histogram ----
ui <- fluidPage(
titlePanel("Hello Shiny!"),
sidebarLayout(
sidebarPanel(
source("sub.R", echo = FALSE, print.eval = FALSE),
),
mainPanel(
plotOutput(outputId = "distPlot")
)
)
)
server <- function(input, output) {
output$distPlot <- renderPlot({
x <- faithful$waiting
ggplot(tibble(x), aes(x=x)) + geom_histogram( binwidth = input$bins)
})
}
shinyApp(ui = ui, server = server)
And the sourced file sub.R:
sliderInput(inputId = "bins",
label = "Number of bins:",
min = 0.1,
max = 5,
value = 1)
Thanks for any help in advance
I found the fix here: add a [1] at the end of the source(.) command:
library(shiny)
library(ggplot2)
# Define UI for app that draws a histogram ----
ui <- fluidPage(
titlePanel("Hello Shiny!"),
sidebarLayout(
sidebarPanel(
source("~/stackoverflow/17150062/sub.R", echo = FALSE, print.eval = FALSE)[1]
),
mainPanel(
plotOutput(outputId = "distPlot")
)
)
)
server <- function(input, output) {
output$distPlot <- renderPlot({
x <- faithful$waiting
ggplot(tibble(x), aes(x=x)) + geom_histogram( binwidth = input$bins)
})
}
shinyApp(ui = ui, server = server)
I am using shinydashboardplus.
I'd like to use the to do list but the example in the gallery is limited to just showing a list without any functionality.
To track a todo list for a user I am reading and writing to a csv for the moment.
I can read the csv to dynamically populate the list. Now I'd like to be able to strike through an item to indicate it is completed using the checked parameter.
The checked items should be removed from the csv.
Ill work on the adding items another day I think....
Here is my example (not reading from csv but from iris for this example).
library(shiny)
library(shinydashboardPlus)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Old Faithful Geyser Data"),
useShinydashboardPlus(),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
),
# Show a plot of the generated distribution
mainPanel(
box(
"Sortable todo list demo",
status = "warning",
todoList(
apply(mtcars,1, function(x)
todoListItem(
label = x[1],
x[2]
)
)
)
)
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
}
# Run the application
shinyApp(ui = ui, server = server)
Here is an approach using renderUI and a reactive data.frame:
library(shiny)
library(shinydashboardPlus)
library(shinyWidgets)
css <- "
.inlinecheckbox .shiny-input-container {
display: inline-block;
width: auto;
}
"
ui <- fluidPage(
tags$style(css),
titlePanel("Dynamic to do list"),
useShinydashboardPlus(),
sidebarLayout(
sidebarPanel(),
mainPanel(
box(
"Sortable todo list demo",
status = "warning",
uiOutput("myToDoList")
)
)
)
)
checkboxIDs <- paste0("checkbox", seq_len(nrow(mtcars)))
mtcars$checked <- FALSE
# Define server logic required to draw a histogram
server <- function(input, output) {
reactiveMtcars <- reactiveVal(mtcars)
observe({
for (i in seq_along(checkboxIDs)) {
if(!is.null(input[[checkboxIDs[1]]])){
mtcars$checked[i] <- input[[checkboxIDs[i]]]
}
}
reactiveMtcars(mtcars)
})
output$myToDoList <- renderUI({
req(reactiveMtcars())
todoListItems <- list()
for(i in seq_len(nrow(reactiveMtcars()))){
todoListItems[[i]] <- todoListItem(
label = div(rownames(reactiveMtcars())[i], style = ""),
span(class = "inlinecheckbox", checkboxInput(inputId = paste0("checkbox", i), label = NULL, value = reactiveMtcars()$checked[i])),
checked = reactiveMtcars()$checked[i],
)
}
todoList(todoListItems)
})
}
shinyApp(ui = ui, server = server)
I am new to R Shiny. I am attempting to create an app that allows a user to subset a data.frame based on multiple variables and then see the resulting data.
Here is a small example data set:
iter,wave,apples
1,1,600
1,1,500
1,1,400
1,2,300
1,2,200
1,2,100
2,1,1000
2,1,1100
2,1,1200
2,2,1300
2,2,1400
2,2,1500
3,1,1100
3,1,2200
3,1,3300
3,2,4400
3,2,5500
3,2,6600
I would like the user to be able to specify the value of iter and of wave and see the resulting data.
Here is my attempt at the Shiny code. I realize I must be making several silly mistakes.
Edit
Here is my revised code. The end result now comes pretty close to what I want. The sidebar is still not being displayed perfectly.
library(shiny)
setwd('C:/Users/mark_/Documents/simple_RShiny_files/explore')
apple.data <- read.csv('subset_data_based_on_multiple_variables.csv',
header = TRUE, stringsAsFactors = FALSE)
ui <- fluidPage(
titlePanel("Subsetting Apple Dataset"),
sidebarLayout(
sidebarPanel(
uiOutput("codePanel")
),
mainPanel(
tableOutput("view")
)
),
selectInput("codeInput", inputId ="data1", label = "Choose Iter", choices = unique(apple.data$iter)),
selectInput("codeInput", inputId ="data2", label = "Choose Wave", choices = unique(apple.data$wave))
)
server <- function(input, output) {
output$codePanel <- renderUI({
})
dataset <- reactive({
subset(apple.data, (iter == input$data1 & wave == input$data2))
})
output$view <- renderTable(dataset())
}
shinyApp(ui = ui, server = server)
The output
The problem is that both selectInputs have the same inputId. This works:
library(shiny)
apple.data <- data.frame(
iter = c(1L,1L,1L,1L,1L,1L,2L,2L,2L,2L,2L,
2L,3L,3L,3L,3L,3L,3L),
wave = c(1L,1L,1L,2L,2L,2L,1L,1L,1L,2L,2L,
2L,1L,1L,1L,2L,2L,2L),
apples = c(600L,500L,400L,300L,200L,100L,1000L,
1100L,1200L,1300L,1400L,1500L,1100L,2200L,3300L,4400L,
5500L,6600L)
)
ui <- fluidPage(
titlePanel("Subsetting Apple Dataset"),
sidebarLayout(
sidebarPanel(
selectInput("codeInput1", label = "Choose Iter", choices = unique(apple.data$iter)),
selectInput("codeInput2", label = "Choose Wave", choices = unique(apple.data$wave))
),
mainPanel(
tableOutput("view")
)
)
)
server <- function(input, output) {
dataset <- reactive({
return(subset(apple.data, (iter == input$codeInput1 & wave == input$codeInput2)))
})
output$view <- renderTable(dataset())
}
shinyApp(ui = ui, server = server)
I am building multiple lm() models using dplyr. I want to allow a user to change the independent variable value in a Shiny app - via shiny::sliderInput(). But only do so where "goodness of fit" say R^2 is greater than a threshold - otherwise disable the slider. I have tried to use the shinyjs::disable() function. See below, but can't get it to work. Any ideas on what I am doing wrong ?
library(shiny)
library(shinyjs)
# Define UI for application that draws a histogram
ui <- shinyUI(fluidPage(
sidebarLayout(
sidebarPanel(
sliderInput("test","Nice number",min = 1,max = 50,value = 30)
),
mainPanel(
textOutput("valueText")
)
)
))
# Define server to disable slider if value selected
server <- shinyServer(function(input, output) {
value <- reactive(input$test)
output$valueText <- renderText(paste(value()))
#How to diasble slider?
reactive(if(value()==35){
shinyjs::disable('test')
}
)
})
# Run the application
shinyApp(ui = ui, server = server)
You have to call useShinyjs() in ui.R.
This is the code:
library(shiny)
library(shinyjs)
# Define UI for application that draws a histogram
ui <- shinyUI(
tagList(
useShinyjs(),
fluidPage(
sidebarLayout(
sidebarPanel(
sliderInput("test","Nice number",min = 1,max = 50,value = 30)
),
mainPanel(
textOutput("valueText")
)
)
)
)
)
# Define server to disable slider if value selected
server <- shinyServer(function(input, output) {
value <- reactive(input$test)
output$valueText <- renderText(paste(value()))
#How to diasble slider?
observeEvent(value(), {
if(value()==35){
shinyjs::disable('test')
}
})
})
# Run the application
shinyApp(ui = ui, server = server)