Shiny Rhino + Shiny.Fluent Reactivity未通过模块进行

ff29svar  于 2023-07-31  发布在  React
关注(0)|答案(1)|浏览(92)

我目前正在尝试使用Appsilon Rhino框架和shiny.fluent UI包建立一个模块化的Shiny应用程序。我试图在用户选择的输入之间获得一些React,以馈送到应用程序中的第二个窗格中,以显示下拉列表的选择,而无需用户返回下拉列表来查看他们选择了什么。数据模块(用户输入)馈送选择模块(显示选择),选择模块馈送到布局模块,布局模块基本上用于格式化和UI布局,布局模块馈送主.R文件,馈送app.R文件。
我已经尝试了几种不同的方法,通过定义特定的React元素并使用observe()和observeEvent(),但似乎无法解决基于用户更改显示的选择。这些将需要不断监测,因为用户可以进行一次选择,然后在同一会话中选择不同的一组列以获得不同的结果。下面各个模块的代码。
---data.R---

box::use(
  shiny.fluent[Dropdown.shinyInput, Separator, updateDropdown.shinyInput],
  shiny[moduleServer, NS, div, textOutput],
  janitor[make_clean_names],
  magrittr[`%>%`],
  dplyr[mutate]
)

column_options <- c('column 1', 'column 2', 'column 3')

#' @export
ui <- function(id) {
  ns <- NS(id)
  div(
    Separator('fields'),
    Dropdown.shinyInput(
      ns('cols'),
      multiSelect = TRUE,
      value = 'Please select columns to return',
      options = column_options
  ))
}

#' @export
server <- function(id) {
  moduleServer(id, function(input, output, session) {
    
    cols_selected <- reactive({
      input$cols})
    
    list(
      cols_selected = cols_selected
    )
  })
}

字符串
---selection.R---

box::use(
  shiny.fluent[GroupedList, DetailsList, Text, Separator],
  shiny[moduleServer, NS, div, textOutput],
  htmlwidgets[JS],
  DBI[dbGetInfo]
)

box::use(
  app/view/data
)

col_headers <- list(
  list(key = 'fields', fieldName = 'fields', name = 'Fields')
)

#' @export
ui <- function(id, cols_selected, fils_selected) {
  
  ns <- NS(id)
  div(
    Separator('selected fields'),
    DetailsList(items = cols_selected(), columns = col_headers)
  )
}

#' @export
server <- function(id) {
  moduleServer(id, function(input, output, session) {
    cols_selected <- data$server('data', cols_selected)
  })
}


---layout.R---

box::use(
  shiny[...],
  shiny.fluent[Stack, fluentPage, Text, Image],
  glue[glue]
)

box::use(
  app/view/selection,
  app/view/data
)

## header UI details ----
header <- tagList(
  div(
    class = "page-title",
    span('App', class = "title"),
    br(),
    span('data', class = "subtitle")
  )
)

## selection pane UI details ----
selection <- selection$ui('selection', cols_selected)

## data pane UI details ----
data <- data$ui('data')

## helper functions ----
# function to create and style overall page
makePage <- function (contents) {
  tagList(
    contents
  )
}

# function to create and style individual cards
makeCard <- function(title, content, size = 12, style = "") {
  div(
    class = glue("card ms-depth-8 ms-sm{size} ms-xl{size}"),
    style = style,
    Stack(
      tokens = list(childrenGap = 5),
      Text(variant = "large", title, block = TRUE),
      content
    )
  )
}

# create base page (without header and footer)
query_page <- makePage(
  div(
    Stack(
      horizontal = T,
      tokens = list(childrenGap = 10),
      makeCard('Choose Data', data, size = 3),
      makeCard('Current selections', selection, size = 3)
    ),
    uiOutput('layout')
  )
)

# function to create layout of header, panes, and footer
layout <- function(mainUI) {
  div(class = 'grid-container',
      div(class = 'header', header),
      div(class = 'main', mainUI)
  )
}

#' @export
ui <- function(id) {
  ns <- NS(id)
  fluentPage(
    layout(query_page)
  )
}

#' @export
server <- function(id) {
  moduleServer(id, function(input, output, session) {
    cols_selected <- data$server('cols')
    selection$server('selection', cols_selected)
  })
}


---main.R---

box::use(
  shiny[tagList, moduleServer, NS],
)

# import modules to main app
box::use(
  app/view/layout
)

#' @export
ui <- function(id) {
  ns <- NS(id)
  tagList(
    data$ui(ns('data')),
    layout$ui(ns('layout'))
  )
}

#' @export
server <- function(id) {
  moduleServer(id, function(input, output, session) {
    data_module <- callModule(data$server('data'))
    cols_selected <- data_module$cols_selected
    selection$server('selection', cols_selected)
    layout$server('layout')
  })
}


---app.R---

# Rhino / shinyApp entrypoint. Do not edit.
rhino::app()


我试过观察和obeserveEvent,但没有工作。我认为主要的问题是我引用每个模块的服务器端到main.R脚本的方式,但我不能找出正确显示数据的组合。

0ve6wy6x

0ve6wy6x1#

问题似乎在于模块和主应用程序之间如何传递React值。要正确处理React性并确保正确显示选择,可以对代码进行以下更改:
在data.R模块中:
您需要修改服务器函数以返回响应值cols_selected,而不是将其放入列表中。

#' @export
server <- function(id) {
  moduleServer(id, function(input, output, session) {
    cols_selected <- reactive({
      input$cols
    })

    return(cols_selected)
  })
}

字符串
在selection.R模块中:
通过调用前面创建的函数,确保从data.R模块中正确检索React值cols_selected。

server <- function(id, cols_selected) {
  moduleServer(id, function(input, output, session) {
    
    return(cols_selected)
  })
}


在main.R模块中:
在检索cols_selected reactive值的方式中有一个小错误。你应该使用data_module对象,而不是直接使用data$server('data')函数。

#' @export
server <- function(id) {
  moduleServer(id, function(input, output, session) {
    data_module <- callModule(data$server, 'data')
    cols_selected <- data_module()
    selection$server('selection', cols_selected)
    layout$server('layout')
  })
}


通过进行这些更改,React性应正确工作,并且用户所做的选择将显示在选择模块中,而无需导航回下拉列表。

相关问题