立即重新单击按钮无效

时间:2020-10-08 11:16:54

标签: r shiny

我有一个Shiny应用程序,允许用户通过单击表格中的按钮来编辑记录笔记。它适用于第一次单击,但是在关闭编辑对话框(“确定”或“取消”)后,该按钮立即变为内部按钮。如果单击第二个按钮,则第一个按钮将再次激活。知道如何解决这个问题吗?

require(shiny)
require(DT)
require(tidyverse)

states_dat = tibble(id = state.abb, name = state.name, pop = state.x77[,1], note = NA_character_)

#------------------------------------------------

# Return the UI for a modal dialog with state update options
editModal = function(conv_id) {
  ns = NS('state-update')
  curr_mon_id <<- conv_id
  
  conv = dplyr::filter(my_dt$df, id == conv_id$id)
  modalDialog(
    h3(paste0('Edit note ', conv_id)),
    textInput(ns("edit_note"), "Note", value = conv$note, width='600px'),
    footer = tagList(
      modalButton("Cancel"),
      actionButton(ns("ok"), "OK")
    )
  )
}

#------------------------------------------------

# Main screen server
dt_server = function(input, output, session) {
  ns = session$ns
  myValue = reactiveValues(check = '')
  
  shinyInput = function(FUN, len, id, ns, ...) {
    inputs = character(len)
    for (i in seq_len(len)) inputs[i] = as.character(FUN(paste0(id, i), ...))
    inputs
  }
  
  my_dt <<- reactiveValues(df = {
    dat = states_dat
    dat$` ` = shinyInput(actionButton, nrow(dat), 'button_', label = "Edit note",
                         onclick = glue::glue('Shiny.onInputChange("{ns("select_button")}", this.id)'))
    dat
  })
  
  observeEvent(input$select_button, {
    selectedRow = as.numeric(strsplit(input$select_button, "_")[[1]][2])
    myValue$check <<- my_dt$df[selectedRow,1]
    showModal(editModal(myValue$check))
  })
  
  output$states_table = DT::renderDT(filter = "top", {
    return(my_dt$df)
  }, escape = FALSE)
}

#------------------------------------------------

# Record Update server
mud_server = function(input, output, session) {
  ns = session$ns
  
  # When OK button is pressed, check if details have changed and if so update postgres db
  observeEvent(input$ok, {
    id = curr_mon_id$id[1]
    
    if(!identical(input$edit_note, states_dat$note[states_dat$id == id])){
      my_dt$df$note[my_dt$df$id == id] = input$edit_note
    }
    
    removeModal()
  })
}

#------------------------------------------------

# Data table UI
dt_ui = function(id){
  ns = NS(id)
  
  tagList(
    titlePanel( h3('State populations'), windowTitle = 'States-Pop'), hr(),
    mainPanel(width=12, DT::DTOutput(ns("states_table"))
    )
  )
}

#------------------------------------------------

ui = fluidPage( dt_ui(id = "states-manager"))

server = function(input, output, session) {
  callModule(module = dt_server , id = "states-manager")
  callModule(module = mud_server , id = "state-update")
}

shinyApp(ui = ui, server = server)

任何其他关于如何改进此应用程序的简短评论都将受到欢迎。这是我第一次使用Shiny模块,因此离最佳配置还差得很远。例如,注释编辑会清除所有当前的表格过滤器。

1 个答案:

答案 0 :(得分:1)

在您的JS中,将select_button设置为相应的id。随后的点击将其设置为相同的id。由于该值不变,因此观察者不会再次触发。如果您单击之间的另一个按钮,则该值将更改两次,然后它将再次起作用。

here对此行为进行了说明。

您可以明确地告诉JS将点击视为事件,而不是通过如链接中所述添加{priority: "event"}来设置值。

因此,以下代码片段将达到目的:

my_dt <<- reactiveValues(df = {
      dat = states_dat
      dat$` ` = shinyInput(actionButton, nrow(dat), 'button_', label = "Edit note",
                           onclick = glue::glue('Shiny.setInputValue("{ns("select_button")}", this.id, {{priority: "event"}})'))
      dat
   })

注意。我使用setInputValue而不是onInputChange,因为后者在Shiny v 1.1中已被软弃用。