Я не прочитал весь ваш пост, потому что он, кажется, содержит несколько вопросов, но я решу главный вопрос, первый, выделенный жирным шрифтом: Как я могу получить доступ к внутренним реактивным значениям модуля и изменить их извне?
Прежде всего, чтобы перейти к предложенному мною решению, я хочу предложить другой способ возврата информации из модуля.Вместо использования значения и атрибута значения вы можете вернуть список, с которым гораздо проще работать.Вот немного измененное приложение:
library(shiny)
moduleUI <- function(id, label=id,min = 0,max = 100,value = 30){
ns <- NS(id)
fluidRow(
column(width=9,
sliderInput(ns("sl"), label=label, min=min, max=max, value=value)
),
column(width=2,
textOutput(ns("changesCount") )
)
)
}
synchModule<-function(session, targetModule, oldModule){
ns<-NS(targetModule)
updateSliderInput(session,ns("sl"),value=oldModule$value() )
##Accessing and changing internal Value of targetModule??
}
module<- function(input, output, session){
rv<-reactiveValues(changesCount=0)
observeEvent(input$sl,rv$changesCount<-rv$changesCount+1)
output$changesCount=renderText(rv$changesCount)
return(list(
value = reactive({ input$sl }),
changes = reactive({ rv$changes }),
print = reactive({ paste0("Num: ", input$sl, "; changes: ", rv$changesCount) })
))
}
ui=fluidPage(
moduleUI("module1"),
moduleUI("module2"),
actionButton("synchButton", "Set Module 2 to state of Module 1."),
textOutput("module1state"),
textOutput("module2state")
)
server= function(input, output, session) {
module1<-callModule(module,"module1")
module2<-callModule(module,"module2")
observeEvent(input$synchButton,
synchModule(session,"module2",module1)
)
output$module1state=renderPrint(module1$print() )
output$module2state=renderPrint(module2$print() )
}
shinyApp(ui, server)
Надеюсь, вы поймете, что его легче читать, работать и расширять.
Теперь к вашему основному вопросу: как получить доступ и изменить внутренние реактивные значения модуля?
Нет.По крайней мере, не напрямую.
Внутреннее состояние, как правило, лучше не изменять кому-либо еще.Существует широко используемая парадигма, называемая методами получения и установки, которую я бы использовал здесь.Вы не заходите напрямую в другой модуль и не изменяете его состояние - это полностью нарушает принцип, лежащий в основе модулей (быть независимым и изолированным).Вместо этого у нас может быть модуль, возвращающий метод получения - в нашем случае это означает возвращение его значений (как я делал выше со списком value
и changes
), а также метод установки - который будет функцией, котораякто-то еще может позвонить, чтобы установить значения внутри модуля.
Если это пока не имеет смысла на 100%, вот суть того, что я имею в виду: добавьте этот «установщик» в список возвратаmodule:
setState = function(value, count) {
updateSliderInput(session, "sl", value = value)
rv$changesCount <- count - 1
}
И теперь нам больше не нужно заходить в модуль и напрямую изменять его состояние, мы можем просто вызвать setState()
!Вот полный измененный код:
library(shiny)
moduleUI <- function(id, label=id,min = 0,max = 100,value = 30){
ns <- NS(id)
fluidRow(
column(width=9,
sliderInput(ns("sl"), label=label, min=min, max=max, value=value)
),
column(width=2,
textOutput(ns("changesCount") )
)
)
}
synchModule<-function(session, targetModule, oldModule){
oldModule$setState(targetModule$value(), targetModule$count())
}
module<- function(input, output, session){
rv<-reactiveValues(changesCount=0)
observeEvent(input$sl,rv$changesCount<-rv$changesCount+1)
output$changesCount=renderText(rv$changesCount)
return(list(
value = reactive({ input$sl }),
count = reactive({ rv$changesCount }),
print = reactive({ paste0("Num: ", input$sl, "; changes: ", rv$changesCount) }),
setState = function(value, count) {
updateSliderInput(session, "sl", value = value)
rv$changesCount <- count - 1
}
))
}
ui=fluidPage(
moduleUI("module1"),
moduleUI("module2"),
actionButton("synchButton", "Set Module 2 to state of Module 1."),
textOutput("module1state"),
textOutput("module2state")
)
server= function(input, output, session) {
module1<-callModule(module,"module1")
module2<-callModule(module,"module2")
observeEvent(input$synchButton,
synchModule(session,module1,module2)
)
output$module1state=renderPrint(module1$print() )
output$module2state=renderPrint(module2$print() )
}
shinyApp(ui, server)