好,这里是您的解决方案。我很高兴找到一个,因为它花了我几个小时。
基本上,如果你想从无(无渲染功能)添加一个模块,它必须通过JavaScript。这有三种措施:
- 创建HTML元素
- 与ionrangeslider.js库
- 注册为滑块创建闪亮回调
如果从闪亮调用inputSlider
,所有三个为你完成。但没有它,我们必须单独做这些事情。好东西,如果你知道该怎么做并不难。
我的代码的重要部分发生在script
的内部。在那里,我创建了元素(您在函数sliderUI
中尝试过之前),然后调用ionRangeSlider
,使其看起来像一个真正的滑块,最后,Shiny.unbindAll()/Shiny.bindAll()
为相应的input
变量创建绑定。
其他增加只是为了说明。
享受!
代码:
library(shiny)
ui <- fixedPage(
fixedRow(
column(width = 4, wellPanel(
h4("Slider Module"),
tags$div(
sliderInput("slider-bins", "Number of Bins:", min = 1, max = 5, value = 3)
),
actionButton("addSliderModule", "Add Slider Module"))
),
column(width = 4, wellPanel(id = "target",
h4("Dynamic Loading Modules"),
p("Clicking on the 'Add' button on the left should add the module here. You should be able to duplicate that slider module as many times as the button is clicked"),
hr(),
tags$script('
Shiny.addCustomMessageHandler("createSlider",
function(ID) {
Shiny.unbindAll();
var targetContainer = document.getElementById("target");
var container = document.createElement("div");
container.setAttribute("class", "form-group shiny-input-container");
var label = document.createElement("label");
label.setAttribute("class", "control-label");
label.setAttribute("for", "ID");
var labelText = document.createTextNode("Number of Bins");
label.appendChild(labelText);
container.appendChild(label);
var input = document.createElement("input");
input.setAttribute("class", "js-range-slider");
input.setAttribute("id", ID);
input.setAttribute("data-min", "1");
input.setAttribute("data-max", "5");
input.setAttribute("data-from", "3");
input.setAttribute("data-step", "1");
input.setAttribute("data-grid", "true");
input.setAttribute("data-grid-num", "4");
input.setAttribute("data-grid-snap", "false");
input.setAttribute("data-prettify-separator", ",");
input.setAttribute("data-keyboard", "true");
input.setAttribute("data-keyboard-step", "25");
input.setAttribute("data-drag-interval", "true");
input.setAttribute("data-data-type", "number");
container.appendChild(input);
targetContainer.appendChild(container);
$("#" + ID).ionRangeSlider();
Shiny.bindAll();
}
);'
)
)),
column(width = 4, wellPanel(
uiOutput("response")
))
)
)
server <- function(input, output, session) {
observeEvent(input$addSliderModule, {
session$sendCustomMessage(type = "createSlider", message = paste0("slider-", input$addSliderModule))
})
output$response <- renderUI({
if(input$addSliderModule >0){
lapply(1:input$addSliderModule, function(x){
output[[paste("response", x)]] <- renderText({paste("Value of slider", x, ":", input[[paste0("slider-", x)]])})
textOutput(paste("response", x))
})
}
})
}
runApp(shinyApp(ui, server))
我无法掌握你实际想要做的事情。你首先想要在一个井中渲染一个Slider,并在Button Click上将其位置更改为另一个?你有没有在服务器中的任何代码来响应你的按钮?为什么renderUI不是你正在寻找的? –
随着我了解它的renderUI,你把一个占位符内的UI功能,然后你写你的控制/小部件内的服务器功能。模块分两部分。一部分你必须添加到UI功能和另一部分添加到服务器功能使用calllModule。如果有帮助,您可以考虑在点击按钮时多次重复模块。重复的模块应该都是独立的。 – MySchizoBuddy
我改进了问题并更好地解释了我想要的视觉 – MySchizoBuddy