我有一个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模块,因此离最佳配置还差得很远。例如,注释编辑会清除所有当前的表格过滤器。
答案 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中已被软弃用。