2017-03-22 1 views
1

많은 웹 사이트에서 목록의 요소 순서를 변경하는 끌어서 놓기 인터페이스가 있습니다. 나는 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]) 
    }) 
    } 
) 

단점 : 목록의 끝에서 순서를 변경하려면 사용자가 올바른 순서로 전체 목록을 선택할 수 있습니다. 하나의 실수와 그는 다시 처음부터 다시 시작해야합니다.

위시리스트 : 이런 종류의 작업을보다 편리하게 만들 수있는 반짝이는 위젯 (다른 패키지에서 가능). 드래그 앤 드롭이 바람직합니다.

답변

4

이렇게하려면 custom input object을 사용할 수 있습니다. 이를 수행 할 라이브러리가 많이 있는데 여기에 this one이라는 예가 있습니다.

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); 

그것은, 그것은 정렬 가능한을 아주 최소한의 생성됩니다

sortableList.js : 여기

는 반짝 앱의 www 폴더에 포함 할 필요가 자바 스크립트 코드를 결합한다 인스턴스를 초기화하고 사용자가 라이브러리의 onUpdate 이벤트를 사용하여 요소를 변경할 때마다 요소의 순서를 반환합니다.

여기 소자 만들 R 코드 예시 앱 :

app.R

sortableList 함수 Sortable 라이브러리 반짝이 바인딩 코드로 sortableList.js 모두 포함
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) 

value에 전달 된 벡터의 값을 유지하는 div를 만듭니다.

내 응용 프로그램 디렉토리는 다음과 같습니다

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

그리고 응용 프로그램을 시작하는 runApp("application-dir")를 사용합니다. 편집 및 상자 밖으로 정렬 목록을 지원 listviewer :

+0

환상적이며 멋지게 작동합니다. 정말 Javascript에 관해서 두 가지를 배워야합니다 :-) –

-1

또한 Shiny htmlwidget 위젯을 사용할 수 있습니다.