我試圖允許用戶從另一個模塊(ui_module1)添加在server_module2中看到的連續 UI 輸出。因此,當他們點擊按鈕時,他們將看到 3 個 UI 物件:textOutput、sliderInput、textInput。我下面的代碼在輸出 UI 物件時停止。如果我不將它包裝在第一個模塊中,它可以正常作業。
謝謝你。
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(shinyWidgets)
library(dplyr)
ui_module2 = function(id) {
ns = NS(id)
uiOutput(ns("finalOut"))
}
server_module2 = function(id) {
moduleServer(id,
function(input, output, session) {
output$finalOut = renderUI({
ns = session$ns
textOutput(p(style = "color: red", paste0("Package Num:", id, sep = "-")))
sliderInput("n", "N", 1, 1000, 500)
textInput("label", "Label")
})
})
}
ui_module1 = function(id) {
ns = NS(id)
actionBttn(ns("actionbutton1"), "Press Button For New UI")
}
server_module1 = function(id) {
moduleServer(id,
function(input, output, session) {
observeEvent(input$actionbutton1, {
i = sprintf('d', input$actionbutton1)
id = sprintf('static%s', i)
print(id)
insertUI(selector = "#actionbutton1",
where = "afterEnd",
ui = ui_module2(id))
server_module2(id)
})
})
}
ui = fluidPage(ui_module1("opt)"))
server = function(input, output, session) {
server_module1("opt)")
}
shinyApp(ui, server)
uj5u.com熱心網友回復:
這是作業代碼。你需要注意很多。這里有一些關鍵點。
- 記得
ns為所有模塊添加。 renderUI只回傳一個物件,如果要回傳多個組件,請使用tagListordiv。insertUI模塊內的選擇器也需要添加ns.
自己檢查代碼是否存在小錯誤。
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(shinyWidgets)
library(dplyr)
ui_module2 = function(id) {
ns = NS(id)
uiOutput(ns("finalOut"))
}
server_module2 = function(id) {
moduleServer(id,
function(input, output, session) {
output$finalOut = renderUI({
ns = session$ns
div(
# not sure what you want with next line, commented, fix your own
# textOutput(p(style = "color: red", paste0("Package Num:", id, sep = "-"))),
sliderInput(ns("n"), "N", 1, 1000, 500),
textInput(ns("label"), "Label")
)
})
})
}
ui_module1 = function(id) {
ns = NS(id)
actionBttn(ns("actionbutton1"), "Press Button For New UI")
}
server_module1 = function(id) {
moduleServer(id,
function(input, output, session) {
ns <- session$ns
observeEvent(input$actionbutton1, {
i = sprintf('d', input$actionbutton1)
id = sprintf('static%s', i)
print(id)
insertUI(selector = paste0("#", ns("actionbutton1")),
where = "afterEnd",
immediate = TRUE,
ui = ui_module2(ns(id)))
server_module2(id)
})
})
}
ui = fluidPage(ui_module1("opt"))
server = function(input, output, session) {
server_module1("opt")
}
shinyApp(ui, server)
了解它是如何作業的
這個案例是嵌套模塊的一個例子。要理解這一點,您需要了解ns命名空間在 Shiny 中是如何作業的。作為Shiny的官方檔案,他們告訴你需要ns(id)在模塊UI上添加,你不需要為模塊服務器這樣做,但他們沒有告訴你為什么。
當您呼叫 時moduleServer(id, function(input, output, session) {...}),此處的會話與您的頂級會話不同。如果您在這里檢查會話,它是一個session_proxy類物件,不再是ShinySession類物件。這就是閃亮moduleServer的內部如何知道模塊內部的運算式。在模塊作用域下呼叫input, output, renderXX,updateXX方法時,會先查詢session物件,如果是session_proxy,則先呼叫session$nsto attach 命名空間。這就是為什么您不需要ns()在服務器上添加的原因,Shiny 為您完成了。
好的,讓我們回到嵌套模塊問題。讓我們通過這個簡單的示例來看看 UI 和服務器上的命名空間是什么。它所做的只是在 UI 和服務器上列印出命名空間。
library(shiny)
uiMod2 <- function(id) {
ns <- NS(id)
div(id = ns(""))
}
serverMod2 <- function(id) {
moduleServer(
id,
function(input, output, session) {
ns <- session$ns
print(ns(""))
})
}
uiMod1 <- function(id) {
ns <- NS(id)
tagList(
div(id = ns("")),
uiMod2(ns("level2"))
)
}
serverMod1 <- function(id) {
moduleServer(
id,
function(input, output, session) {
ns <- session$ns
print(ns(""))
serverMod2("level2")
})
}
ui <- fluidPage(uiMod1("level1"))
server <- function(input, output, session) {serverMod1("level1")}
shinyApp(ui, server)
結果界面

服務器
[1] "level1-"
[1] "level1-level2-"
看到不同?我沒有呼叫ns二級服務器,只是serverMod2("level2"),但命名空間是自動為我附加的。但是,閃亮不知道將其應用于 UI,所以我必須使用uiMod2(ns("level2")).
閃亮不知道的原因全在于session。創建模塊時,需要傳遞function(input, output, session),而創建嵌套模塊時,session第二級模塊的 this 不是ShinySession,而是 a session_proxy,因此將自動附加父命名空間。
UI 的情況有所不同。通常,當您創建類似的模塊 UI 時uiMod2 <- function(id) ...,您不會傳遞會話物件,因此它不知道要繼承哪個命名空間。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/417329.html
標籤:
