I am writing an app that should save a ggplot created into reactive value once user click save button. User can save a few plots and I want to add an option to preview selected plot in Preview tab. It works in the way that user choose a variable which changes the ggplot and then can save a plot by typing a name and preview of that plot is being shown below (for the moment I have a first plot in a list there). The problem is that now when user save any plot and then change Variable input the plot in preview is immediately changed to the one above without saving.
I am wondering what i am doing wrong and what would be possible solution to preview only plots that are saved!
It works all great without modules..
Here is my app:
server.R
library(shinyjs)
library(ggplot2)
library(shiny)
library(shinyFeedback)
source("mod_save_plot_button.R")
#source("mod_preview.R")
shinyServer(function(input, output, session) {
# #define reactive values
value <- reactiveValues(p = list())
data <- reactive(mtcars[[input$var]])
main_Plot <- reactive({
p <-
ggplot(mtcars, aes(x = data())) + geom_histogram(stat = "count", binwidth = 10)
return(p)
})
output$hist <- renderPlot({
main_Plot()
}, res = 96)
########### SAVE PLOT ######
save_plot_buttonServer("1", values = value, new_plot = isolate(main_Plot()))
# ----------- Export tab -----------
# Create a server variable that we can use in the UI for a conditionalPanel
output$saved_plots_exist <- reactive({
length(value$p) > 0
})
outputOptions(output, 'saved_plots_exist', suspendWhenHidden = FALSE)
output$plot_preview <- renderPlot({
value$p[1]
})
})
ui.R
source("mod_save_plot_button.R")
source("mod_preview.R")
shinyUI(
fluidPage(
useShinyjs(),
selectInput("var", "Variable", names(mtcars)),
plotOutput("hist"),
### export ###
save_plot_buttonUI("1"),
conditionalPanel(condition = "!output.saved_plots_exist",
h2("You do not have any saved plots to export")),
conditionalPanel(condition = "output.saved_plots_exist",
fluidRow(column(4, h2("Export"),
#mod export
# export_UI("1"))),
column(
8, h2("Preview"),
#mod preview
plotOutput("plot_preview")
))
)
)
)
)
module:
save_plot_buttonUI <- function(id) {
shiny::tagList(div(
id = NS(id, "save_plot_area"),
inline_ui(textInput(
NS(id, "save_plot_name"), NULL, "",
placeholder = "Enter plot name"
)),
actionButton(NS(id, "save_plot_btn"), "Save plot"),
shinyjs::hidden(span(
id = NS(id, "save_plot_checkmark"),
icon("check")
))
))
}
inline_ui <- function(tag) {
div(style = "display: inline-block", tag)
}
save_plot_buttonServer <- function(id,values = value, new_plot) {
moduleServer(id, function(input, output, session) {
#define reactive values
# When the save button is clicked, add the plot to a list and clear the input
observeEvent(input$save_plot_btn, {
values$click <- rnorm(1)
plot_name <- trimws(input$save_plot_name)
if (plot_name %in% names(values$plots)) {
shinyFeedback::showFeedbackWarning(inputId = "save_plot_name",
text = "Plot with that name already exists.")
} else {
#no message when no name duplication
hideFeedback(inputId = "save_plot_name" )
shinyFeedback::showFeedbackSuccess(inputId = "save_plot_name",
text = "Plot saved",
icon = shiny::icon("ok", lib = "glyphicon"))
#save plot to reactive values
values$p[[plot_name]] <- isolate(new_plot)
updateTextInput(session, "save_plot_name", value = "")
shinyjs::delay(
10,
hideFeedback(inputId = "save_plot_name" )
)
}
})
# Disable the "save" button if the plot name input is empty
observe({
shinyjs::toggleState("save_plot_btn",
condition = nzchar(trimws(input$save_plot_name)))
})
return(values)
})
}