这是我的拖放应用程序:
library(shiny)
library(shinyjqui)
library(shinyjs)
library(dplyr)
###### part 1 ------------------------------------------------------------------
#creating the list of items
df <- structure(list(AG = c("A", "B", "C", "D")),
row.names = c(NA,-4L), class = "data.frame")
# cells of table
connections1 <- paste0("droppable_cell", ifelse(1:2 == 1, "", 1:2), "_1")
connections2 <- paste0("droppable_cell", ifelse(1:2 == 1, "", 1:2), "_2")
connections <- c(connections1, connections2)
# Define a named list for vec_suggestion1
vec_suggestion1 <- list(
droppable_cell_1 = c("A", "B", "A", "B"),
droppable_cell_2 = c("A", "B", "B", "A")
)
# Create the data frame
my_df <- data.frame(connections = connections,
stringsAsFactors = FALSE
)
my_df$vec_suggestion1 <- vec_suggestion1[my_df$connections]
###### part 2 ------------------------------------------------------------------
myComplexTableUI <- div(id = "capture", class = "table-container",
div(class = "grid-table",
id = "montag",
div(class = "grid-row",
div(class = "grid-cell grid-cell-text", "Montag"),
lapply(1:2, function(i) {
div(id = paste0("droppable_cell_", i), class = "grid-cell droppable-cell", "")
})
)
)
)
###### part 3 ------------------------------------------------------------------
# my js
jsCode <- "
$(function() {
function createSortable(day) {
$('[id^=droppable_cell' + day + '_]').sortable({
connectWith: '#A, #B, [id^=droppable_cell' + day + '_]',
drop: function(event, ui) {
$(this).append(ui.draggable);
}
});
}
createSortable('1'); // For day1
createSortable('2'); // For day2
$('[id^=droppable_cell]').on('sortupdate', function(e, ui) {
var cellId = $(this).attr('id');
var item = ui.item.text();
Shiny.setInputValue('dropEvent', {cell: cellId, item: item}, {priority: 'event'});
});
});
shinyjs.pageCol = function(params) {
$('[id^=droppable_cell]').sortable({
connectWith: '#A, #B, [id^=droppable_cell_1], [id^=droppable_cell_2]',
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]));
console.log('dataArray: ', dataArray);
var cacheA = $('#A').html();
var cacheB = $('#B').html();
var cacheGridCells1 = $('[id^=droppable_cell_1]').html();
shinyjs.setSuggestion = function (idxSuggestion) {
$.each(dataArray, function (index, value) {
var cellSelector = '#' + dataArray[index][0];
var classIndex = idxSuggestion === 1 ? 1 : 2;
// Retrieve the items for the current cell from dataArray
var items = dataArray[index][idxSuggestion];
if (typeof items === 'string') {
items = [items]; // Convert to array if there is only one item
}
// Clear the cell content
$(cellSelector).html('');
// Append each item to the cell
$.each(items, function (i, item) {
if (item === null) {
return true;
}
// Determine the style based on the item value
var itemStyle = '';
if (item === 'A') {
itemStyle = 'background-color: #ffcc66;'; // Corresponding to Bootstrap's warning color
} else if (item === 'B') {
itemStyle = 'background-color: #5cb85c;'; // Corresponding to Bootstrap's success color
}
var cellHTML = '<div data-value=\"' + item
+ '\" class=\"btn btn-default ui-sortable-handle\" style=\"' + itemStyle + ' margin: 1px;\" jqui_sortable_idx=\"letters__'
+ (index + 1).toString()
+ '\">'
+ item
+ '</div>';
$(cellSelector).append(cellHTML);
});
});
}
shinyjs.resetDnD = function (params) {
$('#A').html(cacheA).sortable('refresh');
$('#B').html(cacheB).sortable('refresh');
$('[id^=droppable_cell_1]').html(cacheGridCells1).sortable('refresh');
}
};
"
ui <- fluidPage(
useShinyjs(),
extendShinyjs(text = jsCode, functions = c("pageCol", "setSuggestion")),
###### part 4 ------------------------------------------------------------------
# css table design
tags$head(
tags$style(
HTML("
.custom-title-panel button {
margin-left: 10px;
margin-top: 10px;
}
.grid-table {
width: 220px;
border-collapse: collapse;
}
.grid-cell {
width: 100%;
height: 210px;
border: 1px solid black;
background-color: white;
text-align: left;
margin: 0;
padding: 5px;
}
.grid-cell-text {
display: flex;
align-items: center;
justify-content: center;
height: 50px;
background-color: steelblue;
color: white;
font-size: 18px;
}
.table-container {
display: flex;
position: absolute;
left: 260px;
top: 20px;
margin-top: 0px;
overflow: hidden;
}
")
)
),
##################################################################################
# btn reset
tags$script(
HTML(
"$(document).ready(function() {
$('#btn_resetDnD').click(function() {
$('.droppable-cell').html(''); // Remove content from all elements with the class 'droppable_cell'
});
});"
)
),
# my items:
tags$div(
style = "position: relative; height: 50px;", # Setting a height to contain the buttons
tags$div(style = "position: absolute; top: 30px; left: 20px;",
orderInput("A", "", items = df$AG[1], as_source = TRUE, connect = connections, width = "100%", item_class = "warning")
),
tags$div(style = "position: absolute; top: 30px; left: 65px;",
orderInput("B", "", items = df$AG[2], as_source = TRUE, connect = connections, width = "100%", item_class = "success")
)
),
# my table:
myComplexTableUI,
# my buttons:
tags$div(style = "position: absolute; top: 500px; left: 260px; display: flex; flex-direction: row;",
actionButton("btn_suggestion1", "Suggestion1"),
actionButton("btn_resetDnD", "Reset")
)
)
server <- function(input, output, session) {
shinyjs::js$pageCol(my_df)
observeEvent(input$btn_suggestion1, {
shinyjs::disable("btn_suggestion1")
shinyjs::js$setSuggestion(1)
shinyjs::enable("btn_suggestion1")
})
}
shinyApp(ui, server)
应用程序基本上是这样做的:
我想动态地创建'vec_addition1'输入,它目前是硬编码的。我希望系统能够识别并保存用户的输入,当他们拖动到'droppable_cell1'。
vec_suggestion1 <- list(
droppable_cell_1 = c("A", "B", "A", "B"),
droppable_cell_2 = c("A", "B", "B", "A")
)
我的目标是为用户提供拖放A和B的理想组合的能力。此信息应动态保存到“vec_addition2”。随后,A和B的任何其他组合也应该被保存,但保存到'vec_conversion 3','vec_conversion 4'等。沿着每个新向量的创建,应添加相应的新按钮,例如“btn_allocation2”、“btn_allocation3”等。
2条答案
按热度按时间gj3fmq9x1#
下面的方法删除了自定义JS,并为每个单元格使用
orderInput
,这简化了对列表的跟踪。现在我去掉了item_class
参数,以保持简单(我们可以用jqui_sortable()
沿着处理div列表,以保存样式)。但是,保存自定义组合的过程应该是明确的:hiz5n14c2#
在R Shiny中,您可以遵循以下几个步骤来实现这一点
创建一个reactiveValues对象来存储组合向量,然后在用户拖放时进行更新。可以作为空列表初始化。
现在要更新“sortupdate”事件中的reactiveValues对象:在“sortupdate”事件中,检索单元格id和拖动的项,然后使用
update
函数用新的组合更新values$suggestions
对象。现在使用renderUI
和uiOutput
函数添加按钮和相应的操作。在renderUI
中,现在使用observeEvent
函数定义所有按钮的操作在事件中,使用
renderUI
函数根据values$suggestions
中特定组合索引的值为droppable_cell1
和droppable_cell2
生成新的项目列表。希望这对你有帮助!