【问题标题】:In R shiny, how to trigger change in a conditional panel rendered in UI after clicking an action button?在 R Shiny 中,如何在单击操作按钮后触发 UI 中呈现的条件面板中的更改?
【发布时间】:2021-11-06 08:46:28
【问题描述】:

这与我在 2021 年 9 月 3 日发布的帖子类似,只是之前的帖子解决了使用renderUIserver 部分呈现条件面板的情况。为简化起见,我将所有条件面板移至UI 部分,在某些情况下,适用于renderUI 的方法不适用于UI。所以这里...

问题:当运行下面的 MWE 代码时,如果用户在“负债模块”选项卡中(第一次调用时的默认选项卡)并且 (1) 当前正在查看主要的费率值表 (table4)面板(单击主面板顶部的“Rates values”单选按钮后),然后(2)单击侧边栏面板中的“Mod Liaby”操作按钮,然后(3)关闭/重置模态对话框,然后(4) 费率值表保留在主面板中。

同样,如果用户在“负债模块”选项卡中并且 (1) 当前正在主面板中查看负债结构表 (table3),则 (2) 单击侧边栏面板中的“修改利率”操作按钮,然后 (3) 关闭/重置模式对话,然后 (4) 负债结构表保留在主面板中。

我希望单击“Mod Liaby”操作按钮立即导致负债表(“table3”)呈现在主面板中(在模式对话框后面),无论主面板中以前是什么.同样,我想单击“Mod Rate”操作按钮,以立即使费率表(“table4”)呈现在主面板中(在模态对话框后面),而不管主面板中以前是什么。

基本上,我需要在单击侧栏操作按钮之一后触发某种“转到”功能以进行主面板表格渲染。我不知道该怎么做。

我的尝试在下面用# ??? 标记。我的猜测是这是一个非常简单的解决方法,但我的工作知识仍然有限!!顶部的函数,在UI 之上,可以安全地忽略! vectorLiabStructvectorRates 等函数也可以忽略,因为问题在于 UI 部分和表格渲染中的条件面板。

MWE 代码:

    library(shiny);library(shinyMatrix);library(shinyjs)

mainPanelBtns <- function(x,y,z){radioButtons(inputId=x,label="Model view:",choices= y,selected=z,inline=TRUE)}
matrix3Default <- matrix(c(1,24,0,100), 4, 1,dimnames=list(c('A','B','C','D')))
matrix3Input <- function(x, matrix3Default){matrixInput(x,label='Input:',value=matrix3Default,class= 'numeric')} 
matrix3RowHeaders <- function(){c('A','B','C','D')}
matrix4Default <- matrix(c(0.2), 4, 1,dimnames=list(c("A","B","C","D"),NULL))
matrix4Input <- function(x,matrix4Input){matrixInput(x,value = matrix4Input,class = "numeric")}
vectorBaseRate <- function(x,y){
    a <- rep(y,x)
    b <- seq(1:x)
    c <- data.frame(x = b, y = a)
    return(c)}

ui <- 
  pageWithSidebar(
    headerPanel("Model..."),
    sidebarPanel(
      fluidRow("Base Input Panel"),
      conditionalPanel(condition="input.tabselected==4",actionButton('modLiab','Mod Liaby')),
      conditionalPanel(condition="input.tabselected==4||input.tabselected==5",actionButton('modRates','Mod Rate'))
    ), # close sidebar panel
    mainPanel(
      tabsetPanel(
          tabPanel("Liabilities module", value=4,
             mainPanelBtns('mainPanelBtnTab4',c('Liabilities','Rates values'),'Liabilities'),
             conditionalPanel(condition = "input.mainPanelBtnTab4 == 'Liabilities'", tableOutput("table3")),
             conditionalPanel(condition = "input.mainPanelBtnTab4 == 'Rates values'", tableOutput("table4"))
          ), # close tab panel
          tabPanel("Interest rates", value=5,
             mainPanelBtns('mainPanelBtnTab5',c('Rates values'),'Rates values'), 
             conditionalPanel(condition = "input.mainPanelBtnTab5 == 'Rates values'", tableOutput("table5"))
          ), # close tab panel
        id = "tabselected"
      ))) # close tabset panel, main panel, and page with sidebar
    
server <- function(input,output,session)({
  
  rv3        <- reactiveValues( # << rv3 used for matrix 3 (liability structure) inputs
    mat3      = matrix3Input('matrix3',matrix3Default),
    input     = matrix3Default
  ) # close reactive values
  
  matrix4   <- reactive(input$matrix4)
  baseRate  <- function(){vectorBaseRate(60,input$matrix4[1,1])} 
  
  vectorLiabStruct <- reactive({
    if(!isTruthy(input$modLiab)){ 
      df <- matrix3Default
      rownames(df) <- matrix3RowHeaders()}
    else{ 
      req(input$matrix3) 
      rv3$mat3 <- matrix3Input('matrix3',input$matrix3) 
      df <- input$matrix3
      rownames(df) <- matrix3RowHeaders()
      rv3$input <- df
    } # close else
    df})
  
  output$table3 <- renderTable({
    if(!isTruthy(input$modLiab)){ 
      df <- matrix3Default
      rownames(df) <- matrix3RowHeaders()}
    else{ 
      req(input$matrix3) 
      rv3$mat3 <- matrix3Input('matrix3',input$matrix3) 
      df <- input$matrix3
      rownames(df) <- matrix3RowHeaders()
      rv3$input <- df
    } # close else
    df},rownames=TRUE, colnames=TRUE) 
  
  vectorRates <- reactive({
    if (is.null(input$modRates)){df <- NULL}
    else {
      if(input$modRates < 1){df <- cbind(Period = 1:60,BaseRate = 0.2)}
      else {
        req(input$matrix4)
        df <- cbind(Period = 1:60,BaseRate = baseRate()[,2])
      } # close 2nd else
    } # close 1st else
    df}) 
  
  observeEvent(input$modLiab,{ 
    showModal(modalDialog(rv3$mat3,footer=tagList(actionButton("resetLiab","Reset"),modalButton("Close"))))
    tableOutput("table3") # ???
    })
  
  observeEvent(input$resetLiab, {updateMatrixInput(session,'matrix3', matrix3Default)})
  observeEvent(input$resetRates, {updateMatrixInput(session,'matrix4', matrix4Default)})
  
  output$table5<-output$table4<-renderTable({vectorRates()})
  
  observeEvent(input$modRates,
               {showModal(modalDialog(
                 matrix4Input("matrix4",if(is.null(input$matrix4)) matrix4Default else input$matrix4),
                 useShinyjs(),
                 footer = tagList(actionButton("resetRates","Reset"),modalButton("Close"))))
               } # close modalDialog
  ) # close observeEvent
  
}) # close server

shinyApp(ui, server)

【问题讨论】:

  • 您的代码示例太长而且不够简单,很难为您找到问题。
  • OK 会进一步简化,我很害怕
  • 如果我对您的理解正确,您只想在按下 Mod Liaby 按钮(如果它不可见)和有关费率表和按钮的类似行为后切换到负债表?
  • 是的 ismirsehregal 您的理解是正确的。您的解决方案似乎完全按照要求工作,我现在正在检查您的更改。感谢您的耐心和支持!

标签: r shiny shiny-reactivity


【解决方案1】:

我不完全确定我是否正确理解了您的问题,但请检查以下代码并查看 updateRadioButtons 调用:

library(shiny)
library(shinyMatrix)
library(shinyjs)

mainPanelBtns <- function(x, y, z) {
  radioButtons(
    inputId = x,
    label = "Model view:",
    choices = y,
    selected = z,
    inline = TRUE
  )
}

matrix3Default <- matrix(c(1, 24, 0, 100), 4, 1, dimnames = list(c('A', 'B', 'C', 'D')))

matrix3Input <- function(x, matrix3Default) {
  matrixInput(x,
              label = 'Input:',
              value = matrix3Default,
              class = 'numeric')
}

matrix3RowHeaders <- function() {
  c('A', 'B', 'C', 'D')
}

matrix4Default <- matrix(c(0.2), 4, 1, dimnames = list(c("A", "B", "C", "D"), NULL))

matrix4Input <- function(x, matrix4Input) {
  matrixInput(x, value = matrix4Input, class = "numeric")
}

vectorBaseRate <- function(x, y) {
  a <- rep(y, x)
  b <- seq(1:x)
  c <- data.frame(x = b, y = a)
  return(c)
}

ui <- pageWithSidebar(
  headerPanel("Model..."),
  sidebarPanel(
    fluidRow("Base Input Panel"),
    conditionalPanel(condition = "input.tabselected==4", actionButton('modLiab', 'Mod Liaby')),
    conditionalPanel(condition = "input.tabselected==4||input.tabselected==5", actionButton('modRates', 'Mod Rate'))
  ), # close sidebar panel
  mainPanel(
    useShinyjs(),
    tabsetPanel(
      tabPanel(
        "Liabilities module",
        value = 4,
        mainPanelBtns(
          'mainPanelBtnTab4',
          c('Liabilities', 'Rates values'),
          'Liabilities'
        ),
        conditionalPanel(condition = "input.mainPanelBtnTab4 == 'Liabilities'", tableOutput("table3")),
        conditionalPanel(condition = "input.mainPanelBtnTab4 == 'Rates values'", tableOutput("table4"))
      ), # close tab panel
      tabPanel(
        "Interest rates",
        value = 5,
        mainPanelBtns('mainPanelBtnTab5', c('Rates values'), 'Rates values'),
        conditionalPanel(condition = "input.mainPanelBtnTab5 == 'Rates values'", tableOutput("table5"))
      ), # close tab panel
      id = "tabselected"
    ))
) # close tabset panel, main panel, and page with sidebar

server <- function(input, output, session){
  rv3 <- reactiveValues(
    # << rv3 used for matrix 3 (liability structure) inputs
    mat3      = matrix3Input('matrix3', matrix3Default),
    input     = matrix3Default
  ) # close reactive values
  
  matrix4   <- reactive(input$matrix4)
  baseRate  <- function() {
    vectorBaseRate(60, input$matrix4[1, 1])
  }
  
  vectorLiabStruct <- reactive({
    if (!isTruthy(input$modLiab)) {
      df <- matrix3Default
      rownames(df) <- matrix3RowHeaders()
    } else{
      req(input$matrix3)
      rv3$mat3 <- matrix3Input('matrix3', input$matrix3)
      df <- input$matrix3
      rownames(df) <- matrix3RowHeaders()
      rv3$input <- df
    } # close else
    df
  })
  
  output$table3 <- renderTable({
    if (!isTruthy(input$modLiab)) {
      df <- matrix3Default
      rownames(df) <- matrix3RowHeaders()
    } else{
      req(input$matrix3)
      rv3$mat3 <- matrix3Input('matrix3', input$matrix3)
      df <- input$matrix3
      rownames(df) <- matrix3RowHeaders()
      rv3$input <- df
    } # close else
    df
  }, rownames = TRUE, colnames = TRUE)
  
  vectorRates <- reactive({
    if (is.null(input$modRates)) {
      df <- NULL
    } else {
      if (input$modRates < 1) {
        df <- cbind(Period = 1:60, BaseRate = 0.2)
      } else {
        req(input$matrix4)
        df <- cbind(Period = 1:60, BaseRate = baseRate()[, 2])
      } # close 2nd else
    } # close 1st else
    df
  })
  
  observeEvent(input$modLiab, {
    updateRadioButtons(inputId = "mainPanelBtnTab4", selected = "Liabilities")
    updateRadioButtons(inputId = "mainPanelBtnTab5", selected = "Liabilities")
    showModal(modalDialog(rv3$mat3, footer = tagList(
      actionButton("resetLiab", "Reset"), modalButton("Close")
    )))
  })
  
  observeEvent(input$resetLiab, {
    updateMatrixInput(session, 'matrix3', matrix3Default)
  })
  observeEvent(input$resetRates, {
    updateMatrixInput(session, 'matrix4', matrix4Default)
  })
  
  output$table5 <- output$table4 <- renderTable({
    vectorRates()
  })
  
  observeEvent(input$modRates, {
    updateRadioButtons(inputId = "mainPanelBtnTab4", selected = "Rates values")
    updateRadioButtons(inputId = "mainPanelBtnTab5", selected = "Rates values")
    showModal(modalDialog(
      matrix4Input("matrix4", 
                   if (is.null(input$matrix4)){
                     matrix4Default
                   } else {
                     input$matrix4
                   }),
      footer = tagList(
        actionButton("resetRates", "Reset"),
        modalButton("Close")
      )
    ))
  } # close modalDialog
  ) # close observeEvent
} # close server

shinyApp(ui, server)

编辑:将 useShinyjs() 移至 UI - 请参阅 ?useShinyjs()

必须从 Shiny 应用程序的 UI 调用此函数才能使所有 其他shinyjs 函数可以工作。

【讨论】:

  • 好的,我知道 updateRadioButtons 是如何工作的。现在效果很好。现在要在更大的应用程序中使用它,这个 MWE 是从中提取的
猜你喜欢
  • 1970-01-01
  • 2020-01-03
  • 2021-09-19
  • 2021-11-16
  • 2021-08-16
  • 2016-04-19
  • 2020-05-27
  • 1970-01-01
  • 2021-12-06
相关资源
最近更新 更多