使用shinyjqui中的actionButton触发的observeEvent实现拖放功能

问题描述 投票:0回答:1

这是此问题的后续问题使用shinyjqui拖放到网格表中

这是代码:

library(shiny)
library(shinyjqui)

connections <- paste0("droppable_cell_", 1:7) # id of the grid cells

ui <- fluidPage(
    tags$head(tags$script(
        JS(
            "
                       $(function() {
                           $('[id^=droppable_cell]').sortable({
                               connectWith: '#letters',
                               drop: function(event, ui) {
                                         $(this).append(ui.draggable);
                                     }
                           })
                        });
                        "
        )
    ),
    # some styling
    tags$style(
        HTML(
            "
            .grid-table {
                width: 150px;
                border-collapse: collapse;
            }
            .grid-cell {
                width: 100%;
                height: 50px;
                border: 1px solid black;
                background-color: white;
                text-align: center;
                margin: 0;
                padding: 5px;
            }
            .grid-cell-text {
                display: flex;
                align-items: center;
                justify-content: center;
                height: 100%;
                background-color: steelblue;
                color: white;
                font-size: 18px;
            }
            .droppable-cell {
                background-color: lightgray;
            }
            .table-container {
                display: flex;
                position: absolute;
                left: 550px;
                top: 30px;
                margin-top: 0px;
                overflow: hidden;
            }
            "
        )
    )),
    
    div(
        class = "table-container",
        div(
            class = "grid-table",
            id = "my_grid",
            div(
                class = "grid-row",
                div(class = "grid-cell grid-cell-text", "my_grid"),
                div(id = "droppable_cell_1", class = "grid-cell droppable-cell", ""),
                div(id = "droppable_cell_2", class = "grid-cell droppable-cell", ""),
                div(id = "droppable_cell_3", class = "grid-cell droppable-cell", ""),
                div(id = "droppable_cell_4", class = "grid-cell droppable-cell", ""),
                div(id = "droppable_cell_5", class = "grid-cell droppable-cell", ""),
                div(id = "droppable_cell_6", class = "grid-cell droppable-cell", ""),
                div(id = "droppable_cell_7", class = "grid-cell droppable-cell", "")
            )
        ),
        
        orderInput('letters', 'Letters', items = LETTERS[1:7],
                   connect = connections) # defined above
    )
)

server <- function(input, output, session) {
    
}

shinyApp(ui, server)

我正在尝试使用由actionButton触发的observeEvent来实现拖放功能。我的目标是实现向量的拖放,比如说 vec <- c(A, B, C), onto the my_grid table through a button click.

上下文:基本概念涉及在 my_grid 内的特定位置预选择和定位项目。需要注意的是,当项目移动到 my_grid 时,它们也应该从字母部分消失。

r shiny shinyjs shinyjqui
1个回答
0
投票

正如评论中所讨论的,我们为开头字母的放置定义了两个建议,例如这是你给的

connections <- paste0("droppable_cell_", 1:7) # id of the grid cells

vec_suggestion1 <- c("A", NA, "G", NA, "B", "C", "D")
vec_suggestion2 <- c("A", "B", "C", "D", "E", "F", "G")

df <- data.frame(
    connections = connections,
    vec_suggestion1 = vec_suggestion1,
    vec_suggestion2 = vec_suggestion2
)

,我们想实现三个按钮。其中两个用于填充两个建议中给出的网格,其中之一应具有重置拖放的功能。此外,原始的拖放功能必须保持原样。这应该看起来像这样:

我们在这里使用

shinyjs
方法,为按钮添加一些自定义
JS
功能。我在下面解释了重要的变化,并在最后包含了完整的最小工作示例。

按钮像往常一样在

ui
内定义,例如

actionButton("btn_suggestion1", "Suggestion 1")

在服务器内部,我们使用

shinyjs::js$pageCol(df)
    
observeEvent(input$btn_suggestion1, {
    shinyjs::disable("btn_suggestion1")
    shinyjs::js$setSuggestion(1)
    shinyjs::enable("btn_suggestion1")
})

根据您的要求,

observeEvent
由按钮触发,基本上会调用参数为1的函数
setSuggestion
。1是
df
中选项的列索引(因为
JS
索引从0开始) )。函数定义在
pageCol
内部,这是这里的重要部分。
pageCol
获取
df
作为参数并包含

  1. 问题中给出的可排序的原始定义。
  2. 按钮所需的一些变量声明。
  var dataArray = Object.values(params[0]);
  dataArray = dataArray[0].map((col, i) => dataArray.map(row => row[i]));
  
  var cacheLetters = $('#letters').html();
  var cacheGridCells = $('[id^=droppable_cell]').html();

dataArray
只是将
df
转换为
JS
,为了方便起见,我们将其转置。
cacheLetters
cacheGridCells
用于保存字母和网格的原始状态(稍后用于重置按钮)。

  1. setSuggestion
    功能
  shinyjs.setSuggestion = function (idxSuggestion) {
    
    // loop over the array rows
    $.each(dataArray, function (index, value) {

        // define the selector for the grid cell using the first array column
        var cellSelector = '#' + dataArray[index][0];

        // define the new innerHTML of the grid cell such that it will
        // contain the shinyjqui sortable element
        var cellHTML = '<div data-value=\"' 
                        + dataArray[index][idxSuggestion] 
                        + '\" class=\"btn btn-default ui-sortable-handle\" style=\"margin: 1px;\" jqui_sortable_idx=\"letters__' 
                        + (index + 1).toString() 
                        + '\">' 
                        + dataArray[index][idxSuggestion] 
                        + '</div>';
        
        // if the current value is na, next
        if (dataArray[index][idxSuggestion] === null) {
            return true;
        }
        
        // change the innerHTML of the grid cell such that it gets the letter attached
        $(cellSelector).html(cellHTML);
        
        // drop the current letter from the original list
        $('#letters').find(`[data-value='${dataArray[index][idxSuggestion]}']`)[0].remove()
    })
  }
  1. resetDnD
    功能。
  shinyjs.resetDnD = function (params){
    $('#letters').html(cacheLetters).sortable('refresh');
    $('[id^=droppable_cell]').html(cacheGridCells).sortable('refresh');
  }

它只是使用元素的最初缓存的

HTML
来刷新字母和可放置的单元格。

这是完整的示例:

library(shiny)
library(shinyjqui)
library(shinyjs)

connections <- paste0("droppable_cell_", 1:7) # id of the grid cells

vec_suggestion1 <- c("A", NA, "G", NA, "B", "C", "D")
vec_suggestion2 <- c("A", "B", "C", "D", "E", "F", "G")

df <- data.frame(
    connections = connections,
    vec_suggestion1 = vec_suggestion1,
    vec_suggestion2 = vec_suggestion2
)

js <- "shinyjs.pageCol = function(params){

  $('[id^=droppable_cell]').sortable({
     connectWith: '#letters',
     drop: function(event, ui) {
               $(this).append(ui.draggable);
            }
  })
  
  var dataArray = Object.values(params[0]);
  dataArray = dataArray[0].map((col, i) => dataArray.map(row => row[i]));
  
  var cacheLetters = $('#letters').html();
  var cacheGridCells = $('[id^=droppable_cell]').html();
  
  shinyjs.setSuggestion = function (idxSuggestion) {
    
    $.each(dataArray, function (index, value) {
        var cellSelector = '#' + dataArray[index][0];
        var cellHTML = '<div data-value=\"' 
                        + dataArray[index][idxSuggestion] 
                        + '\" class=\"btn btn-default ui-sortable-handle\" style=\"margin: 1px;\" jqui_sortable_idx=\"letters__' 
                        + (index + 1).toString() 
                        + '\">' 
                        + dataArray[index][idxSuggestion] 
                        + '</div>';
        
        if (dataArray[index][idxSuggestion] === null) {
            return true;
        }
        
        $(cellSelector).html(cellHTML);
        
        $('#letters').find(`[data-value='${dataArray[index][idxSuggestion]}']`)[0].remove()
    })
  }
  
  shinyjs.resetDnD = function (params){
    $('#letters').html(cacheLetters).sortable('refresh');
    $('[id^=droppable_cell]').html(cacheGridCells).sortable('refresh');
  }
};
"

ui <- fluidPage(
    useShinyjs(),
    extendShinyjs(text = js, functions = c("pageCol", "resetDnD", "setSuggestion")),
    tags$head(
    # some styling
    tags$style(
        HTML(
            "
            .grid-table {
                width: 150px;
                border-collapse: collapse;
            }
            .grid-cell {
                width: 100%;
                height: 50px;
                border: 1px solid black;
                background-color: white;
                text-align: center;
                margin: 0;
                padding: 5px;
            }
            .grid-cell-text {
                display: flex;
                align-items: center;
                justify-content: center;
                height: 100%;
                background-color: steelblue;
                color: white;
                font-size: 18px;
            }
            .droppable-cell {
                background-color: lightgray;
            }
            .table-container {
                display: flex;
                position: absolute;
                left: 400px;
                top: 30px;
                margin-top: 0px;
                overflow: hidden;
            }
            
            #btn_suggestion1, #btn_suggestion2 {
                background-color: lightblue;
            }
            
            #btn_resetDnD {
                background-color: pink;
            }
            "
        )
    )),
    
    actionButton("btn_suggestion1", "Suggestion 1"),
    actionButton("btn_suggestion2", "Suggestion 2"),
    actionButton("btn_resetDnD", "Reset Drag and Drop"),
    
    div(
        class = "table-container",
        div(
            class = "grid-table",
            id = "my_grid",
            div(
                class = "grid-row",
                div(class = "grid-cell grid-cell-text", "my_grid"),
                div(id = "droppable_cell_1", class = "grid-cell droppable-cell", ""),
                div(id = "droppable_cell_2", class = "grid-cell droppable-cell", ""),
                div(id = "droppable_cell_3", class = "grid-cell droppable-cell", ""),
                div(id = "droppable_cell_4", class = "grid-cell droppable-cell", ""),
                div(id = "droppable_cell_5", class = "grid-cell droppable-cell", ""),
                div(id = "droppable_cell_6", class = "grid-cell droppable-cell", ""),
                div(id = "droppable_cell_7", class = "grid-cell droppable-cell", "")
            )
        ),
        
        orderInput('letters', 'Letters', items = LETTERS[1:7],
                   connect = connections) # defined above
    )
)

server <- function(input, output, session) {
    shinyjs::js$pageCol(df)
    
    observeEvent(input$btn_suggestion1, {
        shinyjs::disable("btn_suggestion1")
        shinyjs::js$setSuggestion(1)
        shinyjs::enable("btn_suggestion1")
    })
    
    observeEvent(input$btn_suggestion2, {
        shinyjs::disable("btn_suggestion2")
        shinyjs::js$setSuggestion(2)
        shinyjs::enable("btn_suggestion2")
    })
    
    observeEvent(input$btn_resetDnD, {
        shinyjs::disable("btn_resetDnD")
        shinyjs::js$resetDnD()
        shinyjs::enable("btn_resetDnD")
    })
}

shinyApp(ui, server)
© www.soinside.com 2019 - 2024. All rights reserved.