DT Datatable with selectInputs 在选择后重置为左侧。

huangapple go评论69阅读模式
英文:

DT Datatable with selectInputs resets back to left after selection

问题

我正在在Shiny应用的DT数据表中的一列中使用selectInputs。多亏了这里的一些帮助,我包括了一些JavaScript来将selectInputs选择化,以保持selectize的样式和搜索功能。这是一个宽表格,因此需要水平滚动才能看到selectInputs。

当我第一次在任何selectInputs中进行选择时,一切都正常。然而,当我第二次单击任何selectInputs时,页面会滚动回到左边,而selectInputs则不可见。我如何保持我拥有的样式和搜索功能,但阻止这种情况发生?

编辑:我还尝试使用shinyWidgets::pickerInput,它没有滚动条问题。然而,在数据表中,对我来说,liveSearch功能不起作用。如果您可以解决这个问题,我将考虑这个问题已得到解答。

示例:

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 = FALSE,
        options = list(
          initComplete = JS(selectize_ids(select_ids))
        )
      )
    })
  }
)
英文:

I am using selectInputs in a column of a DT datatable in a Shiny app. Thanks to some help here, I am including some JavaScript to selectize the selectInputs to keep the style and search capability of selectize. It is a wide table, so the selectInputs require scrolling horizontally to see them.

When I make a selection in any of the selectInputs the first time, everything works fine. However, when I click any of the selectInputs a second time, the page scrolls back to the left and the selectInputs are out of view. How can I keep the style and search capability I have but prevent this from happening?

EDIT: I also tried using shinyWidgets::pickerInput, and it does not have the scrollbar problem. However, the liveSearch feature does not work for me in a datatable. If you can solve that issue, I'll consider this question answered.

Example:

library(shiny)
library(DT)

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

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

答案1

得分: 0

以下是您要翻译的内容:

"The reason that the datatable resets left after the second click on the SelectInput is that selectize has input fields which have position: absolute and left: -10000px. Disabling this fact can be implemented by adding CSS, e.g. for the first SelectInput:

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

This CSS can be generated dynamically for all your SelectInput inside the datatable

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 = '')
}

and can then be included inside the fluidPage by using

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

Complete minimal example:

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 = FALSE,
                options = list(initComplete = JS(selectize_ids(select_ids)))
            )
        })
    }
)

DT Datatable with selectInputs 在选择后重置为左侧。"

请注意,这是您提供的内容的翻译,包括其中的代码部分。

英文:

The reason that the datatable resets left after the second click on the SelectInput is that selectize has input fields which have position: absolute and left: -10000px. Disabling this fact can be implemented by adding CSS, e.g. for the first SelectInput:

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

This CSS can be generated dynamically for all your SelectInput inside the datatable

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

and can then be included inside the fluidPage by using

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

DT Datatable with selectInputs 在选择后重置为左侧。

Complete minimal example:

library(shiny)
library(DT)

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

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


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

答案2

得分: -2

你正在遇到的问题是因为在datatable首次渲染时触发了initComplete事件,然后当用户再次点击其中一个selectInput时会再次触发该事件。initComplete事件会将页面滚动到datatable的顶部,这就是为什么当用户再次点击它们时,selectInput不可见的原因。

为了防止这种情况发生,你可以使用scrollY选项来设置datatable的初始滚动位置。例如,你可以使用以下代码:

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

这将把datatable的初始滚动位置设置为页面顶部的300像素。这将确保当用户点击它们时,selectInput始终可见。

以下是完整的代码:

library(shiny)
library(DT)

# 选择一个或多个输入id的函数
selectize_ids &lt;- function(ids) {
  myStrings &lt;- as.character(sapply(ids, function(id) {
    paste0(&quot;  $(&#39;#&quot;, id, &quot;&#39;).selectize();&quot;)
  }))
  c(
    &quot;function(settings){&quot;,
    myStrings,
    &quot;}&quot;
  )
}

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

这段代码将防止页面在用户点击其中一个selectInput时滚动回顶部。

英文:

The problem you are experiencing is caused by the fact that the initComplete event is fired when the datatable is first rendered, and then again when the user clicks on one of the selectInputs. The initComplete event scrolls the page to the top of the datatable, which is why the selectInputs are out of view when the user clicks on them a second time.

To prevent this from happening, you can use the scrollY option to set the initial scroll position of the datatable. For example, you could use the following code:

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

This will set the initial scroll position of the datatable to 300 pixels from the top of the page. This will ensure that the selectInputs are always visible when the user clicks on them.

Here is the complete code:

library(shiny)
library(DT)

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

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

This code will prevent the page from scrolling back to the top when the user clicks on one of the selectInputs.

huangapple
  • 本文由 发表于 2023年7月18日 13:42:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/76709796.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定