R语言 具有selectInputs的DT数据表在选择后重置回左侧

omtl5h9j  于 2023-07-31  发布在  其他
关注(0)|答案(2)|浏览(86)

我在一个Shiny应用程序的DT数据表的列中使用selectInputs。多亏了here的帮助,我添加了一些JavaScript来选择selectInputs,以保持selectize的样式和搜索功能。它是一个宽表,因此selectInputs需要水平滚动才能看到它们。
当我第一次在任何selectInputs中进行选择时,一切都正常。但是,当我第二次单击任何selectInputs时,页面会向左滚动,selectInputs将显示在视图之外。我怎样才能保持我的风格和搜索能力,但防止这种情况发生?

EDIT:我也试过使用shinyWidgets::pickerInput,它没有滚动条问题。但是,liveSearch特性在数据表中不适用。如果你能解出that issue,我就认为这个问题得到了解答。

范例:

library(shiny)
library(DT)

# Function to selectize one or more input ids
selectize_ids <- function(ids) {
  myStrings <- as.character(sapply(ids, function(id) {
    paste0("  $('#", id, "').selectize();")
  }))
  c(
    "function(settings){",
    myStrings,
    "}"
  )
}

shinyApp(
  ui = fluidPage(
    div(style = "display: none;", selectInput(inputId = "dummy", label = NULL, choices = 1:2)),
    fluidRow(DT::dataTableOutput("mytable"))
  ),
  server = function(input, output, session) {
    df <- as.data.frame(matrix(data = paste0("text", 1:60), ncol = 20))
    colnames(df) <- paste0("column", 1:ncol(df))
    df$myselect <- sapply(1:nrow(df), function(i) {
      as.character(selectInput(
        inputId = paste0("myselect_", i),
        label = NULL,
        choices = c("option1", "option2", "option3")
      ))
    })
    select_ids <- paste0("myselect_", 1:nrow(df))
    output$mytable <- DT::renderDataTable({
      DT::datatable(
        data = df,
        escape = F,
        options = list(
          initComplete = JS(selectize_ids(select_ids))
        )
      )
    })
  }
)

字符串

9jyewag0

9jyewag01#

第二次点击SelectInput后,datatable向左重置的原因是selectize的输入字段包含position: absoluteleft: -10000px。禁用此事实可以通过添加CSS来实现,例如对于第一个SelectInput

#myselect_1-selectized {
    position: relative !important; 
    left: 0px !important;
}

字符串
此CSS可以为datatable中的所有SelectInput动态生成

selectize_css <- function(ids) {
    css_list <- as.character(sapply(ids, function(id) {
        paste0("#",
               id,
               "-selectized {position: relative !important; left: 0px !important;} ")
    }))
    paste(css_list, collapse = '')
}


然后可以使用以下命令将其包含在fluidPage

tags$style(HTML(selectize_css(select_ids)))


的数据
完整的最小示例:

library(shiny)
library(DT)

# Function to selectize one or more input ids
selectize_ids <- function(ids) {
    myStrings <- as.character(sapply(ids, function(id) {
        paste0("  $('#", id, "').selectize();")
    }))
    c("function(settings){",
      myStrings,
      "}")
}

selectize_css <- function(ids) {
    css_list <- as.character(sapply(ids, function(id) {
        paste0("#",
               id,
               "-selectized {position: relative !important; left: 0px !important;} ")
    }))
    paste(css_list, collapse = '')
}

shinyApp(
    ui = fluidPage(
        tags$style(HTML(selectize_css(select_ids))),
        div(style = "display: none;", selectInput(
            inputId = "dummy",
            label = NULL,
            choices = 1:2
        )),
        fluidRow(DT::dataTableOutput("mytable"))
    ),
    server = function(input, output, session) {
        df <- as.data.frame(matrix(data = paste0("text", 1:60), ncol = 20))
        colnames(df) <- paste0("column", 1:ncol(df))
        df$myselect <- sapply(1:nrow(df), function(i) {
            as.character(selectInput(
                inputId = paste0("myselect_", i),
                label = NULL,
                choices = c("option1", "option2", "option3")
            ))
        })
        select_ids <- paste0("myselect_", 1:nrow(df))
        output$mytable <- DT::renderDataTable({
            DT::datatable(
                data = df,
                escape = F,
                options = list(initComplete = JS(selectize_ids(select_ids)))
            )
        })
    }
)

oprakyz7

oprakyz72#

您遇到的问题是由于initComplete事件在第一次呈现datatable时触发,然后当用户单击selectInputs之一时再次触发。initComplete事件将页面滚动到datatable的顶部,这就是为什么当用户第二次单击selectInputs时,它们会显示在视图之外。
为了防止这种情况发生,可以使用scrollY选项设置datatable的初始滚动位置。例如,您可以使用以下代码:

options = list(
  initComplete = JS(selectize_ids(select_ids)),
  scrollY = 300
)

字符串
这将把datatable的初始滚动位置设置为距页面顶部300像素。这将确保selectInputs在用户单击时始终可见。
下面是完整的代码:

library(shiny)
library(DT)

# Function to selectize one or more input ids
selectize_ids <- function(ids) {
  myStrings <- as.character(sapply(ids, function(id) {
    paste0("  $('#", id, "').selectize();")
  }))
  c(
    "function(settings){",
    myStrings,
    "}"
  )
}

shinyApp(
  ui = fluidPage(
    div(style = "display: none;", selectInput(inputId = "dummy", label = NULL, choices = 1:2)),
    fluidRow(DT::dataTableOutput("mytable"))
  ),
  server = function(input, output, session) {
    df <- as.data.frame(matrix(data = paste0("text", 1:60), ncol = 20))
    colnames(df) <- paste0("column", 1:ncol(df))
    df$myselect <- sapply(1:nrow(df), function(i) {
      as.character(selectInput(
        inputId = paste0("myselect_", i),
        label = NULL,
        choices = c("option1", "option2", "option3")
      ))
    })
    select_ids <- paste0("myselect_", 1:nrow(df))
    output$mytable <- DT::renderDataTable({
      DT::datatable(
        data = df,
        escape = F,
        options = list(
          initComplete = JS(selectize_ids(select_ids)),
          scrollY = 300
        )
      )
    })
  }
)


当用户单击selectInputs之一时,此代码将阻止页面滚动回顶部。

相关问题