参见: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 是一个类似列表类型的对象:

  1. server <- function(input, output) {
  2. output$selected_var <- renderText({
  3. "You have selected this"
  4. })
  5. }

需要注意的是,这里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

比如下图是我展示的一个表格:

  1. # some var ----------------------------------------------------------------
  2. test_df <- head(test_df_all)
  3. # Define UI ----
  4. ui <- fluidPage(
  5. titlePanel("widgets tests"),
  6. sidebarLayout(
  7. sidebarPanel(
  8. p("blablabla~"),
  9. selectInput(
  10. "select", strong("Select one to display"),
  11. choices = list("Percent White" = 1, "Choice 2" = 2,
  12. "Choice 3" = 3), selected = 1),
  13. sliderInput("slider1", strong("range your intrests"),
  14. min = 0, max = 100, value = 100)
  15. ),
  16. mainPanel(
  17. dataTableOutput("test_df")
  18. )
  19. )
  20. )
  21. # Define server logic ----
  22. server <- function(input, output) {
  23. output$test_df <- renderDataTable({
  24. test_df
  25. })
  26. }
  27. # Run the app ----
  28. shinyApp(ui = ui, server = server)

06. 将后端内容输出到前端(ui) - 图1

需要注意的是,render函数家族的使用,其内部必须用{} 包围语法。

如:output$test_df <- renderDataTable({test_df})

3. server 中设置接受输入

不难发现,server 中默认有两个形参,我们只是使用了output,而input,则可以用来接受外部的一些信息。

我们可以直接在output 的内部使用它,比如定义一个selected_var 元素,其内容为输出select 交互元素的内容:

  1. # Define UI ----
  2. ui <- fluidPage(
  3. titlePanel("widgets tests"),
  4. sidebarLayout(
  5. sidebarPanel(
  6. p("blablabla~"),
  7. selectInput(
  8. "select", strong("Select one to display"),
  9. choices = list("Herb info", "ingredient info"))
  10. ),
  11. mainPanel(
  12. textOutput("selected_var"),
  13. dataTableOutput("test_df")
  14. )
  15. )
  16. )
  17. # Define server logic ----
  18. server <- function(input, output) {
  19. output$selected_var <- renderText({
  20. paste("You have selected", input$select)
  21. })
  22. output$test_df <- renderDataTable({
  23. test_df
  24. })
  25. }

当我们切换selectInput 交互选项时,输出的内容也随之发生了改变:

06. 将后端内容输出到前端(ui) - 图2

ps:如果是sliderInput 内容,可以通过切片获得其内部元素:

  1. output$min_max <- renderText({
  2. paste("You have chosen a range that goes from",
  3. input$range[1], "to", input$range[2])
  4. })

疑惑:

可是,如果想要通过切换选项来变换数据框或图像,该如何操作呢?

发现并不可以简单的通过sever 中的内容来解决。比如将表格包装在一个列表中,通过接受input 返回的值来获取列表名称对应的数据框获取:

  1. test_df <- head(test_df_all)
  2. tail_df <- tail(test_df_all)
  3. test_list <- list("Herb info" = test_df, "ingredient info" = tail_df)
  4. # Define UI ----
  5. ui <- fluidPage(
  6. titlePanel("widgets tests"),
  7. sidebarLayout(
  8. sidebarPanel(
  9. p("blablabla~"),
  10. selectInput(
  11. "select", strong("Select one to display"),
  12. choices = list("Herb info", "ingredient info"))
  13. ),
  14. mainPanel(
  15. dataTableOutput("test_df"),
  16. textOutput("test_txt")
  17. )
  18. )
  19. )
  20. # Define server logic ----
  21. server <- function(input, output) {
  22. output$test_df <- renderDataTable({
  23. test_list$`input$select`
  24. })
  25. output$test_txt <- renderText({
  26. paste0("output is ", input$select)
  27. })
  28. }

06. 将后端内容输出到前端(ui) - 图3