我混合了动态创建的输入和通常定义的输入。动态创建的输入表现得像一个大的垂直堆叠块,其他输入流动。如何让它们全部流动?
这再现了这个问题:
library(shinydashboard)
shinyApp(
ui = dashboardPage(
dashboardHeader(),
dashboardSidebar(),
dashboardBody(
flowLayout(
uiOutput('input_fields'),
textInput('fielda','Field A',''),
textInput('fieldb','Field B',''),
textInput('fieldc','Field C',''),
textInput('fieldd','Field D','')
)
)
),
server = function(input, output) {
output$input_fields <- renderUI({
lapply(1:4, function(i) {
textInput(paste0('field',i), paste('Field',i),'')
})
})
}
)
目前的布局:
所需的布局:
编辑:忽略字段A,B,C,D小部件。它们只是用于显示其他项目如何包装,但uiOutput则作为一个块。假设所有输入都是动态的。
我想我会改用这段代码。它将renderUI移动到lapply中以创建多个通用输出(在运行时变化,最多10个),我可以使用同样通用的uiOutput语句引用它们。它甚至没有警告不存在的5个输出。不完美,但它会做。可能需要添加一个observeEvent,因为我认为它不会自行反应。
library(shinydashboard)
shinyApp(
ui = dashboardPage(
dashboardHeader(),
dashboardSidebar(),
dashboardBody(
wellPanel(
flowLayout(
uiOutput('field1'),
uiOutput('field2'),
uiOutput('field3'),
uiOutput('field4'),
uiOutput('field5'),
uiOutput('field6'),
uiOutput('field7'),
uiOutput('field8'),
uiOutput('field9'),
uiOutput('field10')
)
)
)
),
server = function(input, output) {
lapply(1:5, function(i) {
output[[paste0('field',i)]] <- renderUI({
textInput(paste0('field',i), paste('Field',i),'')
})
})
}
)
答案 0 :(得分:4)
所有四个动态生成的小部件都被视为一个对象,因为它们包含在列表中。因此很难定位它们。
我能想到的最简单的解决方案是使用最新的闪亮版本中的insertUI
函数,该函数可以使用devtools
包安装:
devtools::install_github("rstudio/shiny")
(Here您可以阅读/详细了解insertUI
和removeUI
)
我们必须告诉insertUI
它应该向用户界面添加新的小部件,我们通过指定参数selector
来实现它(它必须是jQuery选择器接受的字符串)和参数where
(有四个选项指定小工具相对于选择器的方式)
因此,如果我们要在Field 1
下添加新的小部件,我们必须设置selector = "#fielda"
(我们使用#
选择器,因为我们指的是ID)。同样,我们通过设置Field 2
等在selector = "#fieldb"
下添加另一个小部件。按照您的命名约定,我们可以将其概括为:
selector = paste0('#field', letters[i])
在所有情况下,我们也设置where = "afterEnd
。它会将新的小部件放在参考小部件下面。 (没有空间将它们放在参考小部件上方)
现在我们可以将insertUI
打包成for-loop
for (i in 1:4) {
insertUI(
selector = paste0('#field', letters[i]),
where = "afterEnd",
ui = textInput(paste0('field',i), paste('Field',i),'')
)
}
请注意,我们无需在客户端添加任何uiOutput
。
另一个解决方案是在服务器端渲染整个dashboardBody
,创建动态不同的uiOutput
...这不会令人愉快。
当我们看一下图片时,我们可以看到我反过来做了 - 第一行名称中的大写字母和第二行名称中的数字。我希望这不应该是一件大事。)
完整示例:
library(shiny)
library(shinydashboard)
shinyApp(
ui = dashboardPage(
dashboardHeader(),
dashboardSidebar(),
dashboardBody(
flowLayout(
textInput('fielda','Field A',''),
textInput('fieldb','Field B',''),
textInput('fieldc','Field C',''),
textInput('fieldd','Field D','')
)
)
),
server = function(input, output) {
for (i in 1:4) {
insertUI(
selector = paste0('#field', letters[i]),
where = "afterEnd",
ui = textInput(paste0('field',i), paste('Field',i),'')
)
}
}
)
修改强>
如果没有引用小部件,那么您还可以使用非标准评估在服务器端动态定义flowLayout
。
说,您想要生成三个textInput
小部件。您通常可以通过键入
flowLayout(
textInput('fielda', 'Field A'),
textInput('fieldb', 'Field B'),
textInput('fieldc', 'Field C')
)
在客户端。您可以通过在服务器端使用paste0
函数粘贴字符串来执行相同的操作,
i = 1:3
UI <- paste0("flowLayout(",
paste0("textInput(",
"'field", letters[i], "', ",
paste0("'Field ", LETTERS[i], "'"),
")",
collapse = ", "),
")")
将其保存在变量中,例如UI
,然后解析字符串并最终对其进行评估。
eval(parse(text = UI))
在下面的示例中,您有15个动态生成的小部件
完整示例:
library(shiny)
library(shinydashboard)
shinyApp(
ui = dashboardPage(
dashboardHeader(),
dashboardSidebar(),
dashboardBody(
wellPanel(
uiOutput("ui1")
)
)
),
server = function(input, output) {
output[["ui1"]] <- renderUI({
i = 1:15
UI <- paste0("flowLayout(",
paste0("textInput(",
"'field", letters[i], "', ",
paste0("'Field ", LETTERS[i], "'"),
")",
collapse = ", "),
")")
# print(UI)
eval(parse(text = UI))
})
}
)