lslak
lslak

Reputation: 105

renderUI based on the rows in a table

I would like to UI elements based on the rows in a reactive .

This is different from How to create a UI in Shiny from a for loop whose length is based on numeric input?

library(shiny)
library(tidyverse)

x1 <- c(1,2,3,3,3,3)
x2 <- c('red', 'blue', 'green', 'green','green','blue')
x3 <- c('small', 'medium', 'large', 'large', 'large', 'small')



df <-data.frame(x1,x2,x3)


ui <- fluidPage(

    # Sidebar with a slider input for number of bins 
    sidebarLayout(
        sidebarPanel(
            selectizeInput("number",
                        "Number:",
                        choices = c(1,2,3),
                        multiple = TRUE
                    ),
            selectizeInput("color",
                        "color:",
                        choices = c('red', 'blue', 'green'),
                        multiple = TRUE
            ),
            selectizeInput("size",
                        "size:",
                        choices = c('small', 'medium', 'large'),
                        multiple = TRUE
            )
        ),

        # Show a plot of the generated distribution
        mainPanel(
            DT::dataTableOutput("table"),

            lapply(1:3, function(i) {

                    uiOutput(paste0('b', i))
            }



        )
    )
)
)


server <- function(input, output, session) {
    appdata <-reactive({
        df %>%
            filter(
                is.null(input$number) | x1 %in% input$number,
                is.null(input$color) | x2 %in% input$color,
                is.null(input$size)  | x3 %in% input$size
            )
    })

    output$table <- DT::renderDataTable({
        df <- appdata()

        action <-
            DT::dataTableAjax(session, df, outputId = "table")

        DT::datatable(df, options = list(ajax = list(url = action), lengthMenu =c(5,10,15), pageLength = 5), escape = FALSE)
    })

    lapply(1:3, function(i) {
        output[[paste0('b', i)]] <- renderUI({
            strong(paste0('Hi, this is output B#', i))
        })
    })

}


# Run the application 
shinyApp(ui = ui, server = server)

The code above statically loops the number output UI. I need the number of Hi, this is output B#[i] to match the number of rows in the dynamic table. As that table is filtered, the number of output UI should shrink.

mainPanel(
            DT::dataTableOutput("table"),

            lapply(1:nrow(appdata()), function(i) {

                    uiOutput(paste0('b', i))
            }

I was hoping the above would work but that just throws error of could not find function appdata.

Any help would be appreciated. Thank-you.

Upvotes: 1

Views: 218

Answers (1)

lslak
lslak

Reputation: 105

I found a solution to this issue code below works and additionally displays information from the table!

library(shiny)
library(shinydashboard)
library(tidyverse)

x1 <- c(1,2,3,3,3,3)
x2 <- c('red', 'blue', 'green', 'green','green','blue')
x3 <- c('small', 'medium', 'large', 'large', 'large', 'small')


df <-data.frame(x1,x2,x3)


ui <- dashboardPage(
    dashboardHeader(title = "Resource Finder"),

    # Sidebar for inputs 
    dashboardSidebar(
            selectizeInput("number",
                        "Number:",
                        choices = c(1,2,3),
                        multiple = TRUE
                    ),
            selectizeInput("color",
                        "color:",
                        choices = c('red', 'blue', 'green'),
                        multiple = TRUE
            ),
            selectizeInput("size",
                        "size:",
                        choices = c('small', 'medium', 'large'),
                        multiple = TRUE
            )
        ),

        # Show a plot of the generated distribution
    dashboardBody(    

    fluidRow(
        box(
            DT::dataTableOutput("table")
        )
    ),

    fluidRow(

          uiOutput("programinfo")



        )
    )

)


server <- function(input, output, session) {
    appdata <-reactive({
        df %>%
            filter(
                is.null(input$number) | x1 %in% input$number,
                is.null(input$color) | x2 %in% input$color,
                is.null(input$size)  | x3 %in% input$size
            )
    })

    output$table <- DT::renderDataTable({
        df <- appdata()

        action <-
            DT::dataTableAjax(session, df, outputId = "table")

        DT::datatable(df, options = list(ajax = list(url = action), lengthMenu =c(5,10,15), pageLength = 5), escape = FALSE)
    })

    output$programinfo<- renderUI({
        lapply(1:nrow(appdata()), function(i) {
            box(

                h2(appdata()[i,'x2']),
                p(paste0("A Program of: ", appdata()[i,'x2'])),
                h3(appdata()[i,'x3']),
                p(paste( "Hours: ",appdata()[i,3], sep = " "))
            )

                # withTags({
                #     div(
                #         h2(appdata()[i,1]),
                #         h3(appdata()[i,1]),
                #         p(appdata()[i,1]),
                #         body(
                #             b("Monday: "), appdata()[i,1], br(),
                #             b("Sunday: "), appdata()[i,1], br()
                #         )
                #     )
                # })


            })
    })


}

# Run the application 
shinyApp(ui = ui, server = server)

Upvotes: 1

Related Questions