module outer variables aren't updating - r shiny - r

In the main shiny server I have a reactivePoll variable. I am trying to share this updating variable with shiny modules. It shows the initial value but it doesn't update. I am trying to get it to update.
Here is a reprex:
library(shiny)
# Module ----
# module ui
mod_ui <- function(id){
ns = NS(id)
verbatimTextOutput(ns("random_num"))
}
# module server
mod <- function(id, number) {
server <- function(input, output, session) {
output$random_num <- renderPrint(number)
}
moduleServer(id, server)
}
# Shiny App ----
ui <- fluidPage(
tags$span("working random_num"),
verbatimTextOutput("test"),
tags$span("not working, module random num"),
mod_ui("mod_id")
)
server <- function(input, output, session) {
random_num <- reactivePoll(
intervalMillis = 1000,
session = NULL,
checkFunc = function()runif(1),
valueFunc = function()runif(1)
)
output$test <- renderPrint(random_num())
mod("mod_id", number = random_num())
}
shinyApp(ui = ui, server = server)
Any help is greatly appreciated!

Figured a solution. Save the reactivePoll variable into a reactiveValue. Observe the reactiveValue. Curious why this is the case.
library(shiny)
# Module ----
# module ui
mod_ui <- function(id){
ns = NS(id)
verbatimTextOutput(ns("random_num"))
}
# module server
mod <- function(id, number) {
server <- function(input, output, session) {
output$random_num <- renderPrint(number$test)
}
moduleServer(id, server)
}
# Shiny App ----
ui <- fluidPage(
tags$span("working random_num"),
verbatimTextOutput("test"),
tags$span("not working, module random num"),
mod_ui("mod_id")
)
server <- function(input, output, session) {
test <- reactiveValues(
test = runif(1)
)
random_num <- reactivePoll(
intervalMillis = 1000,
session = NULL,
checkFunc = function()runif(1),
valueFunc = function()runif(1)
)
observe(
test$test <- random_num()
)
output$test <- renderPrint(random_num())
mod("mod_id", number = test)
}
shinyApp(ui = ui, server = server)

Related

Rshiny modular application with reactiveValues has session separation issues

I have a shiny application for which I have reproduced a simple example here.
It is a modular shiny application. This one is deployed on shinyapp.io
My problem is that when I open 2 instances of my deployed application, the actions done on one of the windows are applied to the other window
It seems that the problem is caused by the reactiveValues (r_global <- reactiveValues() ) in the server part.
Here is the reproduction of the code.
library(shiny)
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
# MODULE ----
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
counterButton = function(id, label = "Counter") {
ns = NS(id)
tagList(actionButton(ns("button"), label = label),
verbatimTextOutput(ns("out")),
dataTableOutput(ns("table")))
}
counterServer <- function(id, r_global) {
moduleServer(id,
function(input, output, session) {
r_global$count = 0
observeEvent(input$button, {
r_global$count = r_global$count + 1
if (input$button == 3) {
output$table <- renderDataTable({
mtcars
})
} else{
output$table <- renderDataTable({
iris
})
}
})
output$out <- renderText({
r_global$count
})
})
}
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
# UI ----
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
ui = fluidPage(h1("test"), counterButton("counter1", "Counter #1"))
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
# SERVER ----
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
server <- function(input, output, session) {
r_global <- reactiveValues()
counterServer("counter1", r_global = r_global)
}
shinyApp(ui, server)

Unable to access the value of radioButton when created inside a shiny server module

My shinyapp is build using modules, the radioBox component inputId = modelling_type is created in the server, using a renderUI function and stored under outputId = modelling_type_ui
As I'm using modules, I have name spaced my IDs in the mod_ui, and then in order to (attempt!) to use the same name space function in the mod_server I have called it via ns <- parentsession$ns. This doesn't throw an error. But I would now expect to access the value of the RadioBox via input$modelling_type
This isn't working! So I must be calling the value incorrectly.
Here is the code:
library(shiny)
library(shinyalert)
library(shinydashboard)
library(shinyjs)
library(tidyverse)
# modules ------------------------------------------
mod_ui <- function(id){
ns <- NS(id)
fluidPage(
uiOutput(outputId = ns("modelling_type_ui")),
textOutput(outputId = ns("capture"))
)
}
mod_server <- function(id, parentsession){
moduleServer(id,
function(input, output, server){
ns <- parentsession$ns
output$modelling_type_ui = renderUI({
print(input$modelling_type) # this should not be null
radioButtons(
inputId = ns("modelling_type"),
label = "Choose a modelling technique",
choices = c("OLS",
"Bayesian"),
selected = "OLS")
})
output$capture = renderText({ paste0("modelling type selected:", input$modelling_type) })
})
}
# call app ---------------------------------------
# run app
ui <- function(){ mod_ui("mt") }
server <- function(input, output, session){ mod_server("mt", session) }
shinyApp(ui = ui, server = server)
Any help appreciated. Usually I would just call radioButtons in the UI, and use updateradioButtons function in the server, but I'm dealing with a legacy app which uses the below method repeatedly.
To expand on my comment above, here is a MWE that I believe does what you want.
I'm not sure why you're using uiOutput and renderUI. I assume it's needed in your actual use case, but it's not needed here. Also, there's no need to muck about with parentsession and the like.
One reason why your debug print prints NULL is that you haven't defined the radio group at the time you try to print its value.
library(shiny)
library(tidyverse)
mod_ui <- function(id){
ns <- NS(id)
fluidPage(
uiOutput(outputId = ns("modelling_type_ui")),
textOutput(outputId = ns("capture"))
)
}
mod_server <- function(id) {
moduleServer(
id,
function(input, output, session){
ns <- session$ns
output$modelling_type_ui = renderUI({
radioButtons(
inputId = ns("modelling_type"),
label = "Choose a modelling technique",
choices = c("OLS","Bayesian"),
selected = "OLS"
)
})
output$capture <- renderText({
paste0("modelling type selected: ", input$modelling_type)
})
rv <- reactive({
input$modelling_type
})
return(rv)
}
)
}
ui <- function() {
fluidPage(
mod_ui("mt"),
textOutput("returnValue")
)
}
server <- function(input, output, session) {
modValue <- mod_server("mt")
output$returnValue <- renderText({
paste0("The value returned by the module is ", modValue())
})
}
shinyApp(ui = ui, server = server)

How to store the returned value from a Shiny module in reactiveValues?

Version 1 below is a toy module that asks for a user input txt, and return the input to the main Shiny app. The main Shiny app then render the text and output it to the screen.
Here I store the return value of the module in a variable called mytxt and I called it through renderText({ mytxt() }).
However, what I actually want to do is to store the returned value to reactiveValues in the main Shiny app. (It doesn't matter if I output it or not as I want to do further evaluations on that value.) But sadly I found no way in making it works. I'm showing my failed codes in Version 2 below.
Version 1 (Correct)
app.R
library(shiny)
source("module_1.R")
ui <- fluidPage(
returnUI("returntxt"),
textOutput("mytxt")
)
server <- function(input, output, session) {
mytxt <- callModule(returnServer, "returntxt")
output$mytxt <- renderText({ mytxt() })
}
shinyApp(ui, server)
module_1.R
returnUI = function(id) {
ns <- NS(id)
tagList(
textInput(ns("txt"), "Write something")
)
}
returnServer = function(input, output, session) {
mytxt <- reactive({
input$txt
})
return(mytxt)
}
Version 2 (Need help!)
app.R
library(shiny)
source("modules/module_1.R")
ui <- fluidPage(
returnUI("returntxt"),
textOutput("mytxt")
)
server <- function(input, output, session) {
myvals <- reactiveValues(
txt = NULL
)
mytxt <- callModule(returnServer, "returntxt")
myvals$txt <- isolate(mytxt())
output$mytxt <- renderText({ myvals$txt })
}
shinyApp(ui, server)
module.R is the same as Version 1.
I just found the answer by returning reactiveValues from the module and use observe :) Woohoo!
app.R
library(shiny)
source("modules/module_1.R")
ui <- fluidPage(
returnUI("returntxt"),
textOutput("mytxt")
)
server <- function(input, output, session) {
myvals <- reactiveValues(
txt = NULL
)
mytxt <- callModule(returnServer, "returntxt")
observe({
myvals$txt <- mytxt$txt
print(myvals$txt)
})
output$mytxt <- renderText({ myvals$txt })
}
shinyApp(ui, server)
module_1.R
returnUI = function(id) {
ns <- NS(id)
tagList(
textInput(ns("txt"), "Write something")
)
}
returnServer = function(input, output, session) {
myreturn <- reactiveValues()
observe({ myreturn$txt <- input$txt })
return(myreturn)
}

Using shiny's renderUI in Module

this is my first question at stackoverflow. I have a problem with modules and renderUI in shiny (1.0.5).
When I use renderUI in
#### Main Part
ui <- bootstrapPage(
uiOutput("DynamicContent")
)
server <- function(input, output,session) {
S_A <- selectInput("S_A_Input" ,"Change Me for print message",choices=1:3 )
output$DynamicContent <- renderUI({
tagList(S_A)
})
observe({
print(input$S_A_Input)
})
}
shinyApp(ui = ui, server = server)
then changing the selectInput will cause changing input$S_A_Input, so the print will occur. That's fine.
On the other hand, input$S_A_Input seems not to work, if I work with modules:
### Module Part
Module_YYY_Server <- function(input, output, session){
S_A <- selectInput("S_A_Input" ,"Change Me for print message",choices=1:3 )
output$DynamicContent <- renderUI({
tagList(S_A)
})
observe({
print(input$S_A_Input)
})
}
Module_YYY_Ui <- function(id){
ns <- NS(id) # Creates Namespace
tagList(
uiOutput("DynamicContent" %>% ns)
)
}
And then calling the module.
#### Main Part
ui <- bootstrapPage(
Module_YYY_Ui("YYY")
)
server <- function(input, output,session) {
callModule(Module_YYY_Server,"YYY")
}
shinyApp(ui = ui, server = server)
I haven't found a solution to this behaviour.
Late to the party but this is another option to solve your problem using
session$ns("id")
Here how it looks like:
Module_YYY_Server <- function(input, output, session){
output$DynamicContent <- renderUI({
selectInput(session$ns("S_A_Input"), "Change Me for print message", choices = 1:3)
})
output$text <- renderText({
req(input$S_A_Input)
input$S_A_Input})
}
Module_YYY_Ui <- function(id){
ns <- NS(id) # Creates Namespace
tagList(
uiOutput(ns("DynamicContent")),
textOutput(ns("text"))
)
}
ui <- bootstrapPage(
Module_YYY_Ui("YYY")
)
server <- function(input, output,session) {
callModule(Module_YYY_Server,"YYY")
}
shinyApp(ui = ui, server = server)
This is based on the example here
While I am sure your example is simplified, If your input$S_A_Input is not changing based on what you are doing, as is the case in your example, I would not recommend using renderUI. Regardless of that, the reason that your input is not printing is because you are not generating it as an output.
Module_YYY_Server <- function(input, output, session){
output$DynamicContent <- renderUI({
ns <- session$ns
tagList(
selectInput("S_A_Input" %>% ns, "Change Me for print message",choices=1:3 )
)
})
output$text <- renderText({input$S_A_Input})
}
Module_YYY_Ui <- function(id){
ns <- NS(id) # Creates Namespace
tagList(
uiOutput("DynamicContent" %>% ns),
textOutput("text" %>% ns)
)
}

Shiny : get an input from a module

I'm trying to get input from a module to the app server.
here is a example of what I want, the app.R :
library(shiny)
source("test.R")
ui <- fluidPage(
tabPanel("tt", testUI("t"))
)
server <- function(input, output) {
ret <- callModule(test, "testm")
print(ret)
}
shinyApp(ui = ui, server = server)
A test module :
testUI <- function(id) {
ns <- NS(id)
tabPanel(NULL,
textInput(ns("textInput1"), label = h5(""), value = "")
)}
test <- function(input, output, session, data) {
reactive({input$textInput1})
}
I would like print the content of textInput1 from the server function of app.R and to observe it.
Two issues with your code: 1) In the UI, you call the module instance "t", in the server "testm". These need to be identical. 2) The Module returns a reactive; this needs to be evaluated in a reactive context: reactive, observe, or render.
library(shiny)
source("test.R")
ui <- fluidPage(
tabPanel("tt", testUI("testm"))
)
server <- function(input, output) {
ret <- callModule(test, "testm")
observe(print(ret()))
}
shinyApp(ui = ui, server = server)
The solution above solve the problem for the example I provided.
However, i does not solved it for my app :
I my app I have the app.R, a module1.R and a module2.R the module2 is call by the module1 which is himself call by app.R. I want to print the value of 'textInput1' from the module1 function.
app.R:
library(shiny)
source("module1.R")
ui <- fluidPage(
tabPanel("Module 1", module1UI("module1"))
)
server <- function(input, output) {
callModule(module1, "module1")
}
shinyApp(ui = ui, server = server)
module1.R:
source("module2.R")
module1UI <- function(id) {
ns <- NS(id)
tabPanel(NULL,
tabPanel("Module 2", module2UI("module2"))
)}
module1 <- function(input, output, session, data) {
reactive({input$textInput1})
ret <- callModule(module2, "module2")
observe(print(ret()))
}
module2.R:
module2UI <- function(id) {
ns <- NS(id)
tabPanel(NULL,
textInput(ns("textInput1"), label = h5(""), value = "")
)}
module2 <- function(input, output, session, data) {
reactive({input$textInput1})
}

Resources