使用do.call在R Shiny中创建ui



我在看是否可以使用do.call创建一个R Shiny ui函数,但我无法理解下面的问题。首先,如果我做一个基本的例子没有做。调用…

library(shiny)
ui <- fluidPage(
titlePanel("A title"),
fluidRow(column(width = 12,"some content",))
)
server <- function(input, output) {}
shinyApp(ui = ui, server = server)

那么这就如预期的那样呈现了一个页面;标题";以及";一些内容";在下面

然后,如果我尝试使用do.call做我认为完全相同的事情,如下所示。。。

library(shiny)
page_data <- c(
titlePanel("A title"),
fluidRow(column(width = 12,"some content",))
)
ui <- do.call(fluidPage, as.list(page_data))
server <- function(input, output) {}
shinyApp(ui = ui, server = server)

则这不会呈现相同的页面。有趣的是,它运行时没有错误;标题";但不是";一些内容";。有什么想法可以解释为什么它会有不同的表现?还有可能使用do.call类型的接口来实现吗?

您可以在开始时定义列表而不是向量,因此以后不使用as.list()。然而,我不知道为什么使用list()as.list(c()):不同

library(shiny)
page_data <- list(
titlePanel("A title"),
fluidRow(column(width = 12,"some content",))
)
ui <- do.call(fluidPage, page_data)
server <- function(input, output) {}
shinyApp(ui = ui, server = server)

编辑:实际上,我们可以看到这两个表达式之间的一些差异:

list(
titlePanel("A title"),
fluidRow(column(width = 12,"some content",))
)
[[1]]
<h2>A title</h2>
[[2]]
<div class="row">
<div class="col-sm-12">some content</div>
</div>
as.list(c(
titlePanel("A title"),
fluidRow(column(width = 12,"some content",))
))
[[1]]

[[2]]
<h2>A title</h2>
$name
[1] "div"
$attribs
$attribs$class
[1] "row"

$children
$children[[1]]
<div class="col-sm-12">some content</div>

罪魁祸首实际上不是as.list,而是c。闪亮的UI函数并不像人们想象的那样返回纯HTML,而是返回一个shiny.tag对象(如果几个shiny.tag对象被分组在一起,则返回shiny.tag.list列表(。shiny.tag对象是一个列表,其中包含有关所用HTML标记的名称及其子标记的信息(例如,其他标记及其内容,有关更多信息,请查看此处(。当打印shiny.tag对象时,我们之所以看到HTML代码,是因为shiny.tagshiny.tag.list对象有特殊的printas.character方法。

看看fluidRow(column(width = 12,"some content")):的输出

str(fluidRow(column(width = 12,"some content")))
List of 3
$ name    : chr "div"
$ attribs :List of 1
..$ class: chr "row"
$ children:List of 1
..$ :List of 3
.. ..$ name    : chr "div"
.. ..$ attribs :List of 1
.. .. ..$ class: chr "col-sm-12"
.. ..$ children:List of 1
.. .. ..$ : chr "some content"
.. ..- attr(*, "class")= chr "shiny.tag"
- attr(*, "class")= chr "shiny.tag"

内部是一个列表!但是,如果打印,则输出:

print(fluidRow(column(width = 12,"some content")))
<div class="row">
<div class="col-sm-12">some content</div>
</div>

titlePanel("A title")也是如此,它实际上在shiny.tag.list:中生成了2个shiny.tag对象

str(titlePanel("A title"))
List of 2
$ :List of 3
..$ name    : chr "head"
..$ attribs : Named list()
..$ children:List of 1
.. ..$ :List of 3
.. .. ..$ name    : chr "title"
.. .. ..$ attribs : Named list()
.. .. ..$ children:List of 1
.. .. .. ..$ : chr "A title"
.. .. ..- attr(*, "class")= chr "shiny.tag"
..- attr(*, "class")= chr "shiny.tag"
$ :List of 3
..$ name    : chr "h2"
..$ attribs : Named list()
..$ children:List of 1
.. ..$ : chr "A title"
..- attr(*, "class")= chr "shiny.tag"
- attr(*, "class")= chr [1:2] "shiny.tag.list" "list"

如果将其组合为一个列表,则单个shiny.tag对象仍然保留其列表结构,因此do.call(fluidPage, page_data_list)生成UI没有问题。你基本上创建了一个列表列表:

page_data_list <- list(
titlePanel("A title"),
fluidRow(column(width = 12,"some content"))
)
str(page_data_list, max.level = 1)
List of 2
$ :List of 2
..- attr(*, "class")= chr [1:2] "shiny.tag.list" "list"
$ :List of 3
..- attr(*, "class")= chr "shiny.tag"

但是,c尝试组合列表。现有的列表对象不会在新创建的列表中获得自己的列表,但最高的列表级别会合并在一起(c基本上会附加列表(:

page_data <- c(
titlePanel("A title"),
fluidRow(column(width = 12,"some content"))
)
str(page_data, max.level = 1)
List of 5
$         :List of 3
..- attr(*, "class")= chr "shiny.tag"
$         :List of 3
..- attr(*, "class")= chr "shiny.tag"
$ name    : chr "div"
$ attribs :List of 1
$ children:List of 1

CCD_ 23不会更改任何内容,因为CCD_ 24已经是一个列表。

现在shiny.tag对象不再具有正确的结构,do.call(fluidPage, page_data)也不起作用。

最新更新