参见:https://shiny.rstudio.com/tutorial/written-tutorial/lesson4/
前面的内容我们一直都是在围绕ui 内容展开。但是,即使ui 设计的再漂亮,就像是光鲜亮丽的空壳,它的内在还是毫无内容的。
这样的产品对于用户来说,是毫无意义。
我们如何能够将R 中存储的内容,比如数据框,比如图像,绘图展示在ui 界面呢?
因此,下面我们要学会编写server 部分,通过设计不同的内容,实现与ui 中交互元素的联系。
相比之前,我们首先还是需要设计不同的ui,接着就是通过sever 部分控制输出了。
1. 基本的输出类型
还是和交互工具一样,shiny 也提供了很多的内置函数,用来输出不同类型的内容:
Output function | Creates |
---|---|
dataTableOutput |
DataTable |
htmlOutput |
raw HTML |
imageOutput |
image |
plotOutput |
plot |
tableOutput |
table |
textOutput |
text |
uiOutput |
raw HTML |
verbatimTextOutput |
text |
2. server 中设置对象输出
ui 的目的是告诉shiny 把什么东西放在页面的什么位置,而server 则是用来构建这个东西。
server 对象中的output 是一个类似列表类型的对象:
server <- function(input, output) {
output$selected_var <- renderText({
"You have selected this"
})
}
需要注意的是,这里output 中定义的对象名,需要与ui 中的对象一致。
同样对应ui 中的几个输出类型,shiny 也提供了几个对应的server 中的函数:
render function | creates |
---|---|
renderDataTable |
DataTable |
renderImage |
images (saved as a link to a source file) |
renderPlot |
plots |
renderPrint |
any printed output |
renderTable |
data frame, matrix, other table like structures |
renderText |
character strings |
renderUI |
a Shiny tag object or HTML |
比如下图是我展示的一个表格:
# some var ----------------------------------------------------------------
test_df <- head(test_df_all)
# Define UI ----
ui <- fluidPage(
titlePanel("widgets tests"),
sidebarLayout(
sidebarPanel(
p("blablabla~"),
selectInput(
"select", strong("Select one to display"),
choices = list("Percent White" = 1, "Choice 2" = 2,
"Choice 3" = 3), selected = 1),
sliderInput("slider1", strong("range your intrests"),
min = 0, max = 100, value = 100)
),
mainPanel(
dataTableOutput("test_df")
)
)
)
# Define server logic ----
server <- function(input, output) {
output$test_df <- renderDataTable({
test_df
})
}
# Run the app ----
shinyApp(ui = ui, server = server)
需要注意的是,render函数家族的使用,其内部必须用{} 包围语法。
如:output$test_df <- renderDataTable({test_df})
3. server 中设置接受输入
不难发现,server 中默认有两个形参,我们只是使用了output,而input,则可以用来接受外部的一些信息。
我们可以直接在output 的内部使用它,比如定义一个selected_var 元素,其内容为输出select 交互元素的内容:
# Define UI ----
ui <- fluidPage(
titlePanel("widgets tests"),
sidebarLayout(
sidebarPanel(
p("blablabla~"),
selectInput(
"select", strong("Select one to display"),
choices = list("Herb info", "ingredient info"))
),
mainPanel(
textOutput("selected_var"),
dataTableOutput("test_df")
)
)
)
# Define server logic ----
server <- function(input, output) {
output$selected_var <- renderText({
paste("You have selected", input$select)
})
output$test_df <- renderDataTable({
test_df
})
}
当我们切换selectInput 交互选项时,输出的内容也随之发生了改变:
ps:如果是sliderInput 内容,可以通过切片获得其内部元素:
output$min_max <- renderText({
paste("You have chosen a range that goes from",
input$range[1], "to", input$range[2])
})
疑惑:
可是,如果想要通过切换选项来变换数据框或图像,该如何操作呢?
发现并不可以简单的通过sever 中的内容来解决。比如将表格包装在一个列表中,通过接受input 返回的值来获取列表名称对应的数据框获取:
test_df <- head(test_df_all)
tail_df <- tail(test_df_all)
test_list <- list("Herb info" = test_df, "ingredient info" = tail_df)
# Define UI ----
ui <- fluidPage(
titlePanel("widgets tests"),
sidebarLayout(
sidebarPanel(
p("blablabla~"),
selectInput(
"select", strong("Select one to display"),
choices = list("Herb info", "ingredient info"))
),
mainPanel(
dataTableOutput("test_df"),
textOutput("test_txt")
)
)
)
# Define server logic ----
server <- function(input, output) {
output$test_df <- renderDataTable({
test_list$`input$select`
})
output$test_txt <- renderText({
paste0("output is ", input$select)
})
}