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})
}
Related
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)
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)
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)
)
}
I'm developing an app in which I use modules to display different tab's ui content. However it seems like the module does not communicate with the main (or parent) app. It displays the proper ui but is not able to execute the observeEvent function when an actionButton is clicked, it should update the current tab and display the second one.
In my code I have created a namespace function and wrapped the actionButton's id in ns(), however it still does not work. Does anyone knows what's wrong?
library(shiny)
moduleUI <- function(id){
ns <- NS(id)
sidebarPanel(
actionButton(ns("action1"), label = "click")
)
}
module <- function(input, output, session){
observeEvent(input$action1, {
updateTabItems(session, "tabsPanel", "two")
})
}
ui <- fluidPage(
navlistPanel(id = "tabsPanel",
tabPanel("one",moduleUI("first")),
tabPanel("two",moduleUI("second"))
))
server <- function(input, output, session){
callModule(module,"first")
callModule(module,"second")
}
shinyApp(ui = ui, server = server)
The observeEvent works, but since modules only see and know the variables given to them as input parameters, it does not know the tabsetPanel specified and thus cannot update it. This problem can be solved using a reactive Value, which is passed as parameter and which is changed inside the module. Once it's changed, it is known to the main app and can update the tabsetPanel:
library(shiny)
library(shinydashboard)
moduleUI <- function(id){
ns <- NS(id)
sidebarPanel(
actionButton(ns("action1"), label = "click")
)
}
module <- function(input, output, session, tabsPanel, openTab){
observeEvent(input$action1, {
if(tabsPanel() == "one"){ # input$tabsPanel == "one"
openTab("two")
}else{ # input$tabsPanel == "two"
openTab("one")
}
})
return(openTab)
}
ui <- fluidPage(
h2("Currently open Tab:"),
verbatimTextOutput("opentab"),
navlistPanel(id = "tabsPanel",
tabPanel("one", moduleUI("first")),
tabPanel("two", moduleUI("second"))
))
server <- function(input, output, session){
openTab <- reactiveVal()
observe({ openTab(input$tabsPanel) }) # always write the currently open tab into openTab()
# print the currently open tab
output$opentab <- renderPrint({
openTab()
})
openTab <- callModule(module,"first", reactive({ input$tabsPanel }), openTab)
openTab <- callModule(module,"second", reactive({ input$tabsPanel }), openTab)
observeEvent(openTab(), {
updateTabItems(session, "tabsPanel", openTab())
})
}
shinyApp(ui = ui, server = server)
Normally, Shiny has no problem generating plots from within UIs that the user calls reactively, but I've noticed that when using a shiny module to dynamically generate the UI, the plot does not appear.
Below is a minimal example of a modularized shiny app that reproduces the problem; it is supposed to generate a ui with a plot in it when the user presses the "go" button:
library("shiny")
exampleUI <- function(id, label = "example") {
ns <- NS(id)
tagList( actionButton(ns("go"), "Go"), uiOutput(ns("ui")) )
}
ui <- fluidPage( exampleUI("example") )
example <- function(input, output, session) {
observeEvent(input$go, {
output$plot <- renderPlot( plot(1:5, 1:5) )
output$ui <- renderUI( plotOutput("plot") )
})
}
server <- function(input, output) { callModule(example, "example") }
shinyApp(ui, server)
By contrast, the non-modularized version works as expected:
ui <- fluidPage(
tagList( actionButton("go", "Go"), uiOutput("ui") )
)
server <- function(input, output) {
observeEvent(input$go, {
output$plot <- renderPlot( plot(1:5, 1:5) )
output$ui <- renderUI( plotOutput("plot") )
})
}
shinyApp(ui, server)
I would appreciate any pointers on how to make the first code block behave like the second.
library(shiny)
exampleUI <- function(id, label = "example") {
ns <- NS(id)
tagList( actionButton(ns("go"), "Go"), uiOutput(ns("ui")) )
}
example <- function(input, output, session) {
observeEvent(input$go, {
output$plot <- renderPlot( plot(1:5, 1:5) )
ns <- session$ns
output$ui <- renderUI( plotOutput(ns("plot")) )
})
}
ui <- fluidPage( exampleUI("example") )
server <- function(input, output, session) {
callModule(example, "example")
}
shinyApp(ui, server)
Two things:
You referred to exampleUI before defining it (In your actual example, you will probably source the module, so this shouldn't be a problem)
When using renderUI in modules which contain input/output you need to wrap it within ns. Read the section on Using renderUI within modules for more