闪亮的小部件,以更改向量中的元素的顺序

问题描述 投票:3回答:2

在很多网站上,您都有一个拖放界面来更改列表中元素的顺序。我正在寻找类似Shiny的东西。我希望用户能够拖放列表的元素以通过更改顺序来更改优先级。

现在我有一个滥用selectizeInput()的解决方案。这有效,但当选择列表变大时,它很快变得很麻烦。

举例说明:

library(shiny)

shinyApp(
  ui = shinyUI({
    fluidPage(
      title = "Example for ordering objects",
      sidebarLayout(
        sidebarPanel(uiOutput("selection"),
                     actionButton('update',"Update")),
        mainPanel(
          helpText('The order of elements'),
          tableOutput('theorder')
        )
      )
    )
  }),
  server = function(input, output, session) {
    values <- reactiveValues(x = c('Item1','Item2','Item3'))

    output$selection <- renderUI({
      selectizeInput('neworder',
                     'Select new order',
                     choices = values$x,
                     multiple = TRUE)
    })

    output$theorder <- renderTable(
      values$x
    )

    observeEvent(input$update,{
      id <- values$x %in% input$neworder
      values$x <- c(input$neworder, values$x[!id])
    })
  }
)

缺点:要更改列表末尾的顺序,用户必须以正确的顺序选择整个列表。一个错误,他必须重新开始。

愿望清单:一个闪亮的小部件(可能来自另一个包),最好是拖放,这可以使这种动作更方便。

r drag-and-drop shiny
2个回答
6
投票

你可以使用custom input object来做到这一点。有很多库可以做到这一点,这是this one的一个例子。

以下是javascript中的闪亮绑定代码,需要包含在您应用的www文件夹中:

sortableList.js

var sortableListBinding = new Shiny.InputBinding();
$.extend(sortableListBinding, {
  find: function(scope) {
    return $(scope).find(".sortableList");
  },
  getValue: function(el) {
    if (typeof Sortable.active != 'undefined'){
      return Sortable.active.toArray();
    }
    else return "";
  },
  subscribe: function(el, callback) {
    $(el).on("change.sortableListBinding", function(e) {
      callback();
    });
  },
  unsubscribe: function(el) {
    $(el).off(".sortableListBinding");
  },
  initialize: function(el) {
    Sortable.create(el,{
      onUpdate: function (evt) {
          $(el).trigger("change");
    }});
  }
});

Shiny.inputBindings.register(sortableListBinding);

它非常小,它在初始化时创建Sortable实例,并在用户使用库的onUpdate事件更改元素时返回元素的顺序。

这是一个带有R代码的示例应用程序来创建元素:

app.R

library(shiny)
library(htmlwidgets)

sortableList <- function(inputId, value) {
  tagList(
    singleton(tags$head(tags$script(src="http://rubaxa.github.io/Sortable/Sortable.js"))),
    singleton(tags$head(tags$script(src = "sortableList.js"))),
    tags$div(id = inputId,class = "sortableList list-group",
             tagList(sapply(value,function(x){
               tags$div(class="list-group-item","data-id"=x,x)
             },simplify = F)))
  )
}

ui <- fluidPage(
  sortableList('sortable_list',c(2,3,4)),
  sortableList('sortable_list2',c(5,6,7)),
  textOutput('test'),
  textOutput('test2')
)

server <- function(input, output, session) 
{
 output$test <- renderText({input$sortable_list})
 output$test2 <- renderText({input$sortable_list2})
 }

shinyApp(ui=ui, server=server)

sortableList函数包括Sortable库和带有Shiny绑定代码的sortableList.js,并创建包含传递给value的向量值的div。

我的app目录如下:

<application-dir>
|-- www
    |-- sortableList.js
|-- app.R

我使用runApp("application-dir")启动应用程序。


-1
投票

您还可以使用Shiny htmlwidget小部件:listviewer,它支持开箱即用的可编辑和可排序列表。

© www.soinside.com 2019 - 2024. All rights reserved.