I want to do a shiny dashboard where a user is able to load a csv file in a page and to make figures in 2 others. A main page, main, contains a sidebar with the menu and how to navigate between the different pages, interface_input, p1 and p2, all different modules.
I have read a lot of documentation and posts and I don't understand how to "save" the loaded csv in app in order to process the data in the other pages. At first I wanted to stock everything as NULL in a reactiveValues() specified in main and update it along the way, but I can't even load the data into it. I have seen apps where it did work using callModule(), but I wanted to try using moduleServer(), maybe this is not appropriate.
The basic code I use to see if reactivity works is like this :
Main document :
##### Main UI - Sidebar #####
#### Libraries ####
library(shiny)
library(bslib)
#### Import Modules ####
setwd("mypath")
source("Interactive_UI/Interface_input_T.R")
source("Interactive_UI/Page_1.R")
source("Interactive_UI/Page_2.R")
#### Interface ####
ui <- page_sidebar(
title = "Analysis interface",
theme = bs_theme(font_scale = 1),
sidebar = sidebar(
navset_pill_list(
id = "menu.modules",
nav_panel(
value='upload.data',
"Charging data"),
nav_panel(
value='quantitative.analysis',
"Test p1",),
nav_panel(
value='spatial.analysis',
"Test p2",),
selected = 'upload.data'),
tags$br(),
actionButton('report', "Export report")),
uiOutput('uitest')
)
#### Server ####
server <- function(input, output, session) {
output$uitest <- renderUI ({
if (input$menu.modules == 'upload.data') {
return(ui.interface_input('interface'))
} else if (input$menu.modules == 'quantitative.analysis') {
return(ui.p1('p1'))
} else if (input$menu.modules == 'spatial.analysis') {
return(ui.p2('p2'))}
})
global_serv <- server.interface_input("interface")
global.data <- reactiveValuesToList(dtf = NULL, variables = NULL)
observeEvent(input$menu.modules,{
if(input$menu.modules == 'quantitative.analysis'){
message("call serv p1")
server.p1("p1")}
}, ignoreNULL = TRUE, ignoreInit = TRUE)
observeEvent(input$menu.modules, {
if(input$menu.modules == 'spatial.analysis'){
message("call serv spatial")
server.p2("p2")}
}, ignoreNULL = TRUE, ignoreInit = TRUE)
}
shinyApp(ui, server)
Interface Input :
ui.interface_input <- function(id) {
ns <- NS(id)
page_fixed(
div(
style = "position: absolute; top: 10px; right: 20px; z-index: 1000;",
input_dark_mode()),
br(),
titlePanel("Charging data"),
br(),
layout_columns(
card(card_header("Charging data"),
card_body(fileInput(ns("file1"), "CSV File",
multiple = TRUE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
checkboxInput(ns("header"), "Header", TRUE))),
layout_columns(
card(card_header("Choose separator"),
card_body(radioButtons(ns("sep"), "Separator",
choices = c("Virgule" = ",",
"Point virgule" = ";",
"Tab" = "\t"),
selected = ","))),
card(card_header("On display"),
card_body(radioButtons(ns("disp"), "Show",
choices = c(Columns = "col",
Head = "head",
All = "all")))))),
card(card_header("Table data"),
card_body(tableOutput(ns("apercu"))
)))
}
server.interface_input <- function(id) {
moduleServer(id, function(input, output, session){
output$apercu <- renderTable({
req(input$file1)
df <- read.csv(input$file1$datapath,
header = input$header,
sep = input$sep)
global.data$dtf <- df
if (input$disp == "col"){
return(data.frame(t(colnames(df)), check.names=F))
} else if(input$disp == "head") {
return(head(df))
} else {
return(df)}})
return(global.data)
print("saving global.data")
})
}
So with these 2, the data should be loaded and saved, or so I thought since it didn't work.
Page 1 and page 2 are basically the same, with this structure
ui.p1 <- function(id){
ns <- NS(id)
page_fixed(
"Test interactivity between pages",
tableOutput('testp1'))
}
# =================== Serveur ====================
server.p1 <- function(id){
moduleServer(id, function(input, output, session){
output$testp1 <- renderTable({
head(global.data$dtf)}) })
}
Except that page 2 shows the tail of the dataframe.
I have also seen apps using several reactiveVal(), but I fear that would be a lot of reactive values always activated and hard to keep track of. Please feel free to tell me if it would be a better option, I have been stuck for a while on that ![]()
With this set-up I thought the 2 first pages were loading the data in a list, but I seem to be mistaken.
What am I missing? If you think another set up is a better choice, please don't hesitate to tell me, I'll gladly hear you.
Thank you!