В R shiny, как вызвать изменение отображения таблицы на главной панели после нажатия кнопки действия?

#r #shiny #shiny-reactivity

Вопрос:

В приведенном ниже коде MWE при запуске, если пользователь (1) в настоящее время просматривает таблицу значений ставок на главной панели (после нажатия кнопки действия «Значения ставок» в верхней части главной панели), затем (2) нажимает кнопку действия «Изменить структуру обязательств» на боковой панели и вносит изменения в сетку ввода структуры обязательств в последующем модальном диалоговом окне, а затем (3) закрывает модальный диалог, затем (4) пользователь остается в таблице значений ставок на главной панели.

Аналогично, если пользователь (1) в настоящее время просматривает таблицу структуры обязательств на главной панели, затем (2) нажимает кнопку «Изменить тарифы и купоны» на боковой панели и вносит изменения в строку A таблицы ввода матрицы (единственная рабочая строка) в последующем модальном диалоге, а затем (3) закрывает модальный диалог, затем (4) пользователь остается в таблице структуры обязательств на главной панели.

Я бы хотел, чтобы любое изменение сетки ввода после нажатия кнопки «Изменить структуру обязательств» приводило к отображению таблицы обязательств (« table3 «) на главной панели, независимо от того, что было ранее на главной панели. Аналогично, я бы хотел, чтобы любое изменение сетки ввода после нажатия кнопки «Изменить тарифы и купоны» приводило к отображению таблицы тарифов (« table4 «) на главной панели, независимо от того, что было ранее на главной панели.

По сути, мне нужно запустить какую-то функцию «Перейти к» для отображения таблицы главной панели после внесения изменений во входную сетку в модальном диалоговом окне. Я не знаю, как это сделать. В приведенном ниже MWE мои неудачные попытки выполнить такого рода «Перейти» отмечены» # ATTEMPT >».

Код MWE:

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

colnames(matrix3Default) <- paste0("Series ",1:ncol(matrix3Default))

matrix3Default <- matrix(c(1,24,0,100),4,1,dimnames=list(matrix3Headers(), NULL))

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

matrix3Input <- function(x, matrix3Default){
  matrixInput(x,label =  'Input series terms into below grid:',
              value =  matrix3Default, 
              rows  =  list(extend=FALSE,names=TRUE), 
              cols  =  list(extend=TRUE,names=TRUE,editableNames=FALSE,delete=TRUE),
              class =  'numeric')}

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

matrix4Input <- function(x,matrix4Input){
  matrixInput(x,value = matrix4Input,
              rows = list(extend=FALSE,names=TRUE),
              cols = list(extend=FALSE,names=FALSE,editableNames=FALSE),
              class = "numeric")}

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

vectorBaseRatePlot <- function(w,x,y,z){plot(w[,1],sapply(w[,2], function(x)gsub("%","",x)),
                                             main=x,xlab=y,ylab=z,type="b")}

ui <- 
  pageWithSidebar(
    headerPanel("Model..."),
    sidebarPanel(fluidRow(helpText(h5(strong("Base Input Panel")),align="center")),uiOutput("Panels")),
    mainPanel(
      tabsetPanel(
        tabPanel("Liabilities module", value=4,
                 fluidRow(h5(strong(helpText("Select model output to view:")))),
                 fluidRow(
                   actionButton('showLiabStructBtn','Liabilities'),
                   actionButton('showRatesValueBtn','Rates values'),
                   actionButton('showRatesPlotBtn','Rates plots')), 
                 uiOutput('showResults')), 
        id = "tabselected"))) 

server <- function(input,output,session)({
  
  showResults <- reactiveValues()
  rv          <- reactiveValues( # Used for matrix 3 (liability structure) inputs
    mat3       = matrix3Input('matrix3',matrix3Default),
    input      = matrix3Default,
    colHeader  = colnames(input))
  matrix4     <- reactive(input$matrix4)
  baseRate    <- function(){vectorBaseRate(60,input$matrix4[1,1])} 
  
  output$Panels <- renderUI({
    tagList( 
      conditionalPanel(condition="input.tabselected==4",
                       actionButton('modLiabStruct','Modify Liabilities Structure'),
                       actionButton('modRates','Modify Rates and Coupons'))
    ) # close tagList
  }) # close renderUI
  
  vectorLiabStruct <- reactive({
    if(!isTruthy(input$modLiabStruct)){ # << Generates default table when first invoking the App
      df <- matrix3Default
      n <- dim(df)[2]
      colnames(df) <- paste("Series", 1:n)
      rownames(df) <- matrix3Headers()
    }
    else{ # 
      req(input$matrix3) 
      rv$mat3 <- matrix3Input('matrix3',input$matrix3) 
      df <- input$matrix3
      n <- dim(df)[2]
      colnames(df) <- paste("Series", 1:n)
      rownames(df) <- matrix3Headers()
      rv$input <- df
    } # close else
    df
  })
  
  output$table3 <- renderTable({
    if(!isTruthy(input$modLiabStruct)){
      df <- matrix3Default
      n <- dim(df)[2]
      colnames(df) <- paste("Series", 1:n)
      rownames(df) <- matrix3Headers()
    }
    else{  
      req(input$matrix3) 
      rv$mat3 <- matrix3Input('matrix3',input$matrix3)
      df <- input$matrix3
      n <- dim(df)[2]
      colnames(df) <- paste("Series", 1:n)
      rownames(df) <- matrix3Headers()
      rv$input <- df
    } # close else
    df
  },rownames=TRUE, colnames=TRUE) # close output$table3
  
  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
  }) # close reactive
  
  output$table4 <- renderTable({vectorRates()})
  
  observeEvent(input$modLiabStruct,{
    showModal(modalDialog( 
      rv$mat3,
      footer = tagList(
        actionButton("resetLiabStruct","Reset"),
        modalButton("Close")
      ), # close tag list
    ))} # close show modal and modal dialog
    # ATTEMPT >  {showResults$showme <- tagList(tableOutput("table3"))}
  ) # close observe event
  
  observeEvent(input$showLiabStructBtn,
               {showResults$showme <- tagList(tableOutput("table3"))},ignoreNULL = FALSE)  
  
  observeEvent(input$resetLiabStruct, {updateMatrixInput(session,'matrix3', matrix3Default)})
  observeEvent(input$resetRatesStruct, {updateMatrixInput(session,'matrix4', matrix4Default)})
  
  observeEvent(input$showRatesValueBtn,
               {showResults$showme <- tagList(tableOutput("table4"))},ignoreNULL = TRUE)
  
  output$graph1 <-renderPlot(vectorBaseRatePlot(vectorRates(),"A Variable","Period","Rate"))
  observeEvent(input$showRatesPlotBtn,{showResults$showme <- plotOutput("graph1")})
  
  output$showResults <- renderUI({showResults$showme})
  
  observeEvent(input$modRates,
               {showModal(modalDialog(
                 matrix4Input("matrix4",if(is.null(input$matrix4)) matrix4Default else input$matrix4),
                 useShinyjs(),
                 footer = tagList(
                   actionButton("resetRatesStruct","Reset"), 
                   modalButton("Close")
                 )))} # close taglist, modalDialog, showModal, and showModal function
               # ATTEMPT > {showResults$showme <- tagList(tableOutput("table4"))}
  ) # close observeEvent
  
}) # close server

shinyApp(ui, server)
 

Ответ №1:

У тебя была хорошая попытка. Просто переместите свое «гото» внутрь фигурных скобок:

 {showModal(modalDialog(
      matrix4Input("matrix4",if(is.null(input$matrix4)) matrix4Default else input$matrix4),
      useShinyjs(),
      footer = tagList(
        actionButton("resetRatesStruct","Reset"), 
        modalButton("Close")
      )))
      showResults$showme <- tagList(tableOutput("table4")) ### this line 
    } ## above this curly brace
 

Комментарии:

1. Дополнительным преимуществом этого «перехода» является то, что изменяемая базовая таблица отображается в фоновом режиме под модальным диалогом, поэтому вы можете видеть свои изменения, отраженные в таблице главной панели в режиме реального времени. A

2. Да, мне действительно понравился этот эффект. Реактивные значения, используемые таким образом, дают нам гораздо больше контроля над выводом только элементов$; например , вы можете иметь, скажем, содержимое правой боковой панели на основе «переключателя» реактивного значения и изменять его в зависимости от того, где пользователь перемещается в приложении. отличный эффект пользовательского интерфейса!

Ответ №2:

Возможно, вы ищете это.

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

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

matrix3Default <- matrix(c(1,24,0,100),4,1,dimnames=list(matrix3Headers(), NULL))
colnames(matrix3Default) <- paste0("Series ",1:ncol(matrix3Default))


matrix3Input <- function(x, matrix3Default){
  matrixInput(x,label =  'Input series terms into below grid:',
              value =  matrix3Default, 
              rows  =  list(extend=FALSE,names=TRUE), 
              cols  =  list(extend=TRUE,names=TRUE,editableNames=FALSE,delete=TRUE),
              class =  'numeric')}

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

matrix4Input <- function(x,matrix4Input){
  matrixInput(x,value = matrix4Input,
              rows = list(extend=FALSE,names=TRUE),
              cols = list(extend=FALSE,names=FALSE,editableNames=FALSE),
              class = "numeric")}

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

vectorBaseRatePlot <- function(w,x,y,z){plot(w[,1],sapply(w[,2], function(x)gsub("%","",x)),
                                             main=x,xlab=y,ylab=z,type="b")}

ui <- 
  pageWithSidebar(
    headerPanel("Model..."),
    sidebarPanel(fluidRow(helpText(h5(strong("Base Input Panel")),align="center")),uiOutput("Panels")),
    mainPanel(
      tabsetPanel(
        tabPanel("Liabilities module", value=4,
                 fluidRow(h5(strong(helpText("Select model output to view:")))),
                 fluidRow(
                   actionButton('showLiabStructBtn','Liabilities'),
                   actionButton('showRatesValueBtn','Rates values'),
                   actionButton('showRatesPlotBtn','Rates plots')), 
                 uiOutput('showResults')), 
        id = "tabselected"))) 

server <- function(input,output,session)({
  
  showResults <- reactiveValues()
  rv          <- reactiveValues( # Used for matrix 3 (liability structure) inputs
    mat3       = matrix3Input('matrix3',matrix3Default),
    input      = matrix3Default,
    colHeader  = colnames(input))
  matrix4     <- reactive(input$matrix4)
  baseRate    <- function(){vectorBaseRate(60,input$matrix4[1,1])} 
  
  output$Panels <- renderUI({
    tagList( 
      conditionalPanel(condition="input.tabselected==4",
                       actionButton('modLiabStruct','Modify Liabilities Structure'),
                       actionButton('modRates','Modify Rates and Coupons'))
    ) # close tagList
  }) # close renderUI
  
  vectorLiabStruct <- reactive({
    if(!isTruthy(input$modLiabStruct)){ # << Generates default table when first invoking the App
      df <- matrix3Default
      n <- dim(df)[2]
      colnames(df) <- paste("Series", 1:n)
      rownames(df) <- matrix3Headers()
    }
    else{ # 
      req(input$matrix3) 
      rv$mat3 <- matrix3Input('matrix3',input$matrix3) 
      df <- input$matrix3
      n <- dim(df)[2]
      colnames(df) <- paste("Series", 1:n)
      rownames(df) <- matrix3Headers()
      rv$input <- df
    } # close else
    df
  })
  
  output$table3 <- renderTable({
    if(!isTruthy(input$modLiabStruct)){
      df <- matrix3Default
      n <- dim(df)[2]
      colnames(df) <- paste("Series", 1:n)
      rownames(df) <- matrix3Headers()
    }
    else{  
      req(input$matrix3) 
      rv$mat3 <- matrix3Input('matrix3',input$matrix3)
      df <- input$matrix3
      n <- dim(df)[2]
      colnames(df) <- paste("Series", 1:n)
      rownames(df) <- matrix3Headers()
      rv$input <- df
    } # close else
    df
  },rownames=TRUE, colnames=TRUE) # close output$table3
  
  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
  }) # close reactive
  
  output$table4 <- renderTable({vectorRates()})
  
  observeEvent(input$modLiabStruct,{
    showModal(modalDialog( 
      rv$mat3,
      footer = tagList(
        actionButton("resetLiabStruct","Reset"),
        #modalButton("Close")
        actionButton("close1","Close")
      ), # close tag list
    ))} # close show modal and modal dialog
    # ATTEMPT >  {showResults$showme <- tagList(tableOutput("table3"))}
  ) # close observe event
  
  observeEvent(input$close1,{
    removeModal()
    showResults$showme <- tagList(tableOutput("table3"))
  })
  
  observeEvent(input$showLiabStructBtn,
               {showResults$showme <- tagList(tableOutput("table3"))},ignoreNULL = FALSE)  
  
  observeEvent(input$resetLiabStruct, {updateMatrixInput(session,'matrix3', matrix3Default)})
  observeEvent(input$resetRatesStruct, {updateMatrixInput(session,'matrix4', matrix4Default)})
  
  observeEvent(input$showRatesValueBtn,
               {showResults$showme <- tagList(tableOutput("table4"))},ignoreNULL = TRUE)
  
  output$graph1 <-renderPlot(vectorBaseRatePlot(vectorRates(),"A Variable","Period","Rate"))
  observeEvent(input$showRatesPlotBtn,{showResults$showme <- plotOutput("graph1")})
  
  output$showResults <- renderUI({showResults$showme})
  
  observeEvent(input$modRates,
               {showModal(modalDialog(
                 matrix4Input("matrix4",if(is.null(input$matrix4)) matrix4Default else input$matrix4),
                 useShinyjs(),
                 footer = tagList(
                   actionButton("resetRatesStruct","Reset"), 
                   #modalButton("Close")
                   actionButton("close2","Close")
                 )))} # close taglist, modalDialog, showModal, and showModal function
               # ATTEMPT > {showResults$showme <- tagList(tableOutput("table4"))}
  ) # close observeEvent
  
  observeEvent(input$close2,{
    removeModal()
    showResults$showme <- tagList(tableOutput("table4"))
  })
  
}) # close server

shinyApp(ui, server)
 

Комментарии:

1. Да, именно то, что я искал. Снова я спасен YBS! То, что вы здесь сделали, ясно, спасибо вам за то, что вы четко изложили изменения. Таким образом, я смогу понять, что происходит, и узнать что-то важное.