如何解决使用do.call在R Shiny中创建ui
我正在查看是否可以使用do.call创建R Shiny ui函数,并且不知所措,无法理解以下问题。首先,如果我不使用do.call ...
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"),))
)
ui <- do.call(fluidPage,as.list(page_data))
server <- function(input,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"),))
)
[[1]]
<h2>A title</h2>
[[2]]
<div class="row">
<div class="col-sm-12">some content</div>
</div>
as.list(c(
titlePanel("A title"),))
))
[[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.list
对象组合在一起,则返回shiny.tag
列表)。
shiny.tag
对象是一个列表,其中包含有关使用的HTML标签名称及其子元素的信息(例如,其他标签及其内容,有关更多信息,请查看here)。
我们在打印shiny.tag
对象时看到HTML代码的原因是因为print
和as.character
对象有特殊的shiny.tag
和shiny.tag.list
方法。>
看看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
中生成了2个shiny.tag.list
对象:
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 [1:2] "shiny.tag.list" "list"
如果将其组合为列表,则单个shiny.tag
对象仍然保留其列表结构,因此do.call(fluidPage,page_data_list)
生成UI没问题。
您基本上可以创建一个列表列表:
page_data_list <- list(
titlePanel("A title"),"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"),"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
as.list(page_data)
不会做任何更改,因为page_data
已经是列表。
现在shiny.tag
对象不再具有正确的结构,并且do.call(fluidPage,page_data)
不起作用。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。