I have to create a Shiny/ShinyDashboard app which basically creates a bunch of tables for various teams. Users will select their team from the sidebar and then they will have several tab panels to choose from depending on the data. See here:
Now the requirement is that I have to split the data for each tab panel into distinct datatables and -because of the data- I have to generate this dynamically.
I came up with the following code (reprex down here) but since I'm quite new to Shiny, I wondered if:
I could split UI and data code even more
there is frankly a better way to do this
library(shiny)
library(shinydashboard)
library(datasets)
library(dplyr)
library(DT)
cars <- mtcars
irises <- iris
cars$team <- sample(c("Team1", "Team2"), nrow(cars), replace = TRUE)
irises$team <-
sample(c("Team1", "Team2"), nrow(irises), replace = TRUE)
# UI
ui <- dashboardPage(
dashboardHeader(title = "Teams"),
dashboardSidebar(sidebarMenu(
menuItem("Team 1",
tabName = "tab_team1",
icon = icon("dashboard")),
menuItem("Team 2",
tabName = "tab_team2",
icon = icon("dashboard"))
)),
dashboardBody(tabItems(
tabItem(tabName = "tab_team1",
fluidRow(
tabBox(
title = "",
width = "100%",
tabPanel(title = "A",
uiOutput("Team1_content_A")),
tabPanel(title = "B",
uiOutput("Team1_content_B"))
)
)),
tabItem(tabName = "tab_team2",
fluidRow(
tabBox(
title = "",
width = "100%",
tabPanel(title = "A",
uiOutput("Team2_content_A")),
tabPanel(title = "B",
uiOutput("Team2_content_B"))
)
))
))
)
server <- function(input, output, session) {
lapply(1:2, function(i) {
t <- paste0("Team", i)
table <- cars %>%
filter(team == t)
output[[paste0(t, "_content_A")]] <- renderUI({
lapply(sort(unique(table$gear)), function(i) {
id <- paste0(t, "_content_A_", i)
output[[id]] <-
DT::renderDataTable(datatable(table[table$gear == i, ]))
fluidRow(
box(
width = "100%",
title = paste0("Gears: ", i),
status = "info",
solidHeader = TRUE,
collapsible = TRUE,
DT::dataTableOutput(id)
)
)
})
})
table2 <- irises %>%
filter(team == t)
output[[paste0(t, "_content_B")]] <- renderUI({
lapply(sort(unique(table2$Species)), function(i) {
id <- paste0(t, "_content_B_", i)
output[[id]] <-
DT::renderDataTable(datatable(table2[table2$Species == i, ]))
fluidRow(
box(
width = "100%",
title = paste0("Species: ", i),
status = "info",
solidHeader = TRUE,
collapsible = TRUE,
DT::dataTableOutput(id)
)
)
})
})
})
}
shinyApp(ui, server)
Echo to #Limey, I would also suggest to use shiny modules https://mastering-shiny.org/scaling-modules.html. There are two reasons.
Reduce unnecessary computation. Currently the computation is run for all the four panels (team1_tabA, team1_tabB, team2_tabA, team2_tabB) at the same time. Ideally, as you add more features or data in the future, you would want to only run the necessary computation when certain action is performed. (i.e. when user click team1_tabA, only the required tables is calculated, no need to calculate tables for other tabs.). Modules can help achieve it.
More flexible control over UI and Server. Currently your app has the same server function and outputs for all the four panels, it works for now. But if in the future you want the four panels to have different layout and outputs, the current coding style might prompt you to write more complex and repeated code. And modules can help you get rid of the repeat and help with more flexible control over the UI and server.
Here is a modularized version of your shiny app. I encountered some issues with using namespace (NS(id)) in the dynamic UI (renderUI), and thanks to the feedback from #YBS Why the shiny dynamic UI + modules does not give the desired output?, the problem is solved, and the modularized shiny is able to run.
## module UI
tab_ui <- function(id) {
ns <- NS(id) ## namespace function
uiOutput(ns("content"))
}
## module Server
tab_server <- function(id, data, Team, var) {
moduleServer(id, function(input, output, session) {
ns <- session$ns ## call namespace in the server
table <- reactive({
data %>% filter(team == Team)
})
output$content <- renderUI({
lapply(sort(unique(table()[[var]])), function(i) {
idd <- paste0("content_", i)
output[[idd]] <-
DT::renderDataTable(datatable(table()[table()[[var]] == i, ]))
fluidRow(
box(
width = "100%",
title = paste0(var, " ", i),
status = "info",
solidHeader = TRUE,
collapsible = TRUE,
DT::dataTableOutput(ns(idd)) ## !!! need to use namespace
)
)
})
})
})
}
## library
library(shiny)
library(shinydashboard)
library(datasets)
library(dplyr)
library(DT)
## data
cars <- mtcars
irises <- iris
cars$team <- sample(c("Team1", "Team2"), nrow(cars), replace = TRUE)
irises$team <-
sample(c("Team1", "Team2"), nrow(irises), replace = TRUE)
## UI
ui <- dashboardPage(
dashboardHeader(title = "Teams"),
dashboardSidebar(sidebarMenu(
menuItem("Team 1",
tabName = "tab_team1"
),
menuItem("Team 2",
tabName = "tab_team2"
)
)),
dashboardBody(tabItems(
tabItem(
tabName = "tab_team1",
fluidRow(
tabBox(
title = "",
width = "100%",
tabPanel(
title = "A",
tab_ui("team1_tabA") ## module ui
),
tabPanel(
title = "B",
tab_ui("team1_tabB") ## module ui
)
)
)
),
tabItem(
tabName = "tab_team2",
fluidRow(
tabBox(
title = "",
width = "100%",
tabPanel(
title = "A",
tab_ui("team2_tabA") ## module ui
),
tabPanel(
title = "B",
tab_ui("team2_tabB") ## module ui
)
)
)
)
))
)
## server
server <- function(input, output, session) {
# module server
tab_server("team1_tabA", data = cars, Team = "Team1", var = "gear")
tab_server("team1_tabB", data = irises, Team = "Team1", var = "Species")
tab_server("team2_tabA", data = cars, Team = "Team2", var = "gear")
tab_server("team2_tabB", data = irises, Team = "Team2", var = "Species")
}
shinyApp(ui, server)
Related
I would like the name of the variables to change according to a text typed in textInput.
For example, when I typed "Stack Overflow" in "A1" field, this name ("Stack Overflow") would appear as the new name, instead conj1.
My code:
library(shiny)
library(shinydashboard)
header <- dashboardHeader(title = "Dashboard", titleWidth = 300)
sidebar <- dashboardSidebar(width = 300,
sidebarMenu(
menuItem(text = "Simulador", tabName = "simulador1",icon = icon("dashboard"))
)
)
body <- dashboardBody(
column(id = "c1", width = 12,
textInput(inputId = "ar1", label = "A 1", placeholder = "Digite")
),
column(id = "colsimul4", width = 12,
textInput(inputId = "lvl1", value = 1,label = "Nível 1", placeholder = "Digite")
),
column(width = 12, tableOutput(outputId = "new"))
)
server <- function(session, input, output) {
fpred_1 <- function(x) {
x
}
predattr1 <- reactive({
fpred_1(x = input$ar1)
})
pred_1 <- reactive({
fpred_1(x = input$lvl1)
})
output$new <- renderTable({
isolate(expr = conj1 <- predattr1())
experiment <- expand.grid(conj1 = c(pred_1()))
isolate(expr = experiment)
})
}
ui <- dashboardPage(header, sidebar, body)
shinyApp(ui, server)
I would like the name of the variables conj to be modified according to what is typed in the field A1
I tried this:
isolate(expr = conj1 <- predattr1())
But doesn't work.
For example, if I typed "Stack Overflow", this name appears instead of conj1.
The values change normally, only the variable names do not.
Edit
I tried that too:
output$new <- renderTable({
isolate(expr = conj1 <- predattr1())
x <- names(predattr1())
experiment <- expand.grid(
colnames(x)[1] = c(pred_1())
)
expr = experiment
})
Nothing...
library(shiny)
library(shinydashboard)
################################################################################
# UI
################################################################################
# Header
header <- dashboardHeader(title = "Dashboard", titleWidth = 300)
# Sidebar
sidebar <- dashboardSidebar(width = 300,
sidebarMenu(menuItem(
text = "Simulador",
tabName = "simulador1",
icon = icon("dashboard")
)))
# Body
body <- dashboardBody(
column(
id = "c1",
width = 12,
# Text input 1
textInput(
inputId = "ar1",
label = "A1",
placeholder = "Digite"
)
),
column(
id = "colsimul4",
width = 12,
# Text input 2
textInput(
inputId = "lvl1",
value = 1,
label = "Nível 1",
placeholder = "Digite"
)
),
# Table appears below text inputs in same column/panel
column(width = 12, tableOutput(outputId = "new"))
)
ui <- dashboardPage(header, sidebar, body)
################################################################################
# Server
################################################################################
server <- function(session, input, output) {
# Create table
experiment <- reactive({
df <- expand.grid(req(input$lvl1))
colnames(df) <- req(input$ar1)
return(df)
})
# Render table
output$new <- renderTable({
experiment()
})
}
shinyApp(ui, server)
I designed a Shiny app with a DT that can detect if the input fields changes and automatically update the values. Below is a screen shot and my code. This app works as I expected. When running this app, values are updated accordingly in DT based on the input values.
# Load the packages
library(tidyverse)
library(shiny)
library(DT)
# Create an empty data frame
dat <- tibble(
Input = c("SliderInput", "RadioButtons", "TextInput"),
Value = NA_character_
)
ui <- fluidPage(
titlePanel("DT: Document the Input Values"),
sidebarLayout(
sidebarPanel = sidebarPanel(
# The input widgets
sliderInput(inputId = "Slider", label = "The SliderInput", min = 1, max = 10, value = 5),
br(),
radioButtons(inputId = "Radio", label = "The RadioButtons", choices = c("A", "B", "C")),
br(),
textInput(inputId = "Text", label = "The TextInput", value = "Enter text ...")
),
mainPanel = mainPanel(
# The datatable
DTOutput(outputId = "d1")
)
)
)
server <- function(input, output, session){
# Save the dat to a reactive object
dat_save <- reactiveValues(df = dat)
output$d1 <- renderDT(dat, options = list(pageLength = 5), editable = TRUE, rownames = TRUE)
# Save the condition of the data table d1
d1_proxy <- dataTableProxy("d1")
# Edit the data table
observeEvent(input$d1_cell_edit, {
dat_save$df <- editData(dat_save$df, input$d1_cell_edit, d1_proxy)
})
# Update the input numbers for each cell
observeEvent(input$Slider, {
dat_save$df[1, "Value"] <- as.character(input$Slider)
})
observeEvent(input$Radio, {
dat_save$df[2, "Value"] <- input$Radio
})
observeEvent(input$Text, {
dat_save$df[3, "Value"] <- input$Text
})
observe({
replaceData(d1_proxy, dat_save$df, resetPaging = FALSE)
})
}
shinyApp(ui, server)
However, when I transferred the same code to a shinydahsboard with more than one tab. The DT cannot update the values when first initialize the app. Below is a screenshot and the code.
# Load the packages
library(tidyverse)
library(shiny)
library(shinydashboard)
library(DT)
# Create an empty data frame
dat <- tibble(
Input = c("SliderInput", "RadioButtons", "TextInput"),
Value = NA_character_
)
ui <- function(request) {
dashboardPage(
# The header panel
header = dashboardHeader(title = ""),
# The sidebar panel
sidebar = dashboardSidebar(
# The sidebar manual
sidebarMenu(
id = "tabs",
# Tab 1
menuItem(
text = "Tab1",
tabName = "Tab1"
),
# Tab 2
menuItem(
text = "DT Example",
tabName = "DT_E"
)
)),
# The main panel
body = dashboardBody(
tabItems(
tabItem(
# The tab name
tabName = "Tab1",
h2("Placeholder")
),
# Tab 2: DT example
tabItem(
# The tab name
tabName = "DT_E",
h2("DT: Document the Input Values"),
sidebarPanel(
# The input widgets
sliderInput(inputId = "Slider", label = "The SliderInput", min = 1, max = 10, value = 5),
br(),
radioButtons(inputId = "Radio", label = "The RadioButtons", choices = c("A", "B", "C")),
br(),
textInput(inputId = "Text", label = "The TextInput", value = "Enter text ...")
),
# The datatable
DTOutput(outputId = "d1")
)
)
)
)
}
server <- function(input, output, session){
# Save the dat to a reactive object
dat_save <- reactiveValues(df = dat)
output$d1 <- renderDT(dat, options = list(pageLength = 5), editable = TRUE, rownames = TRUE)
# Save the condition of the data table d1
d1_proxy <- dataTableProxy("d1")
# Edit the data table
observeEvent(input$d1_cell_edit, {
dat_save$df <- editData(dat_save$df, input$d1_cell_edit, d1_proxy)
})
# Update the input numbers for each cell
observeEvent(input$Slider, {
dat_save$df[1, "Value"] <- as.character(input$Slider)
})
observeEvent(input$Radio, {
dat_save$df[2, "Value"] <- input$Radio
})
observeEvent(input$Text, {
dat_save$df[3, "Value"] <- input$Text
})
observe({
replaceData(d1_proxy, dat_save$df, resetPaging = FALSE)
})
}
shinyApp(ui, server)
Notice that if there is only one tab in the shinydashboard, the DT will work. If changed any input values after initializing the app, the DT will also work. But it is a mystery to me why the DT cannot work in the first place when the shinydashboard has multiple tabs. Any suggestions or comments would be great.
After further search, I found a solution from this post and this post. For some reasons, the default setting for shinydashboard is to ignore hidden objects starting the second tab. In my case, adding outputOptions(output, "d1", suspendWhenHidden = FALSE) solves the issue. Below is the complete code.
# Load the packages
library(tidyverse)
library(shiny)
library(shinydashboard)
library(DT)
# Create an empty data frame
dat <- tibble(
Input = c("SliderInput", "RadioButtons", "TextInput"),
Value = NA_character_
)
ui <- function(request) {
dashboardPage(
# The header panel
header = dashboardHeader(title = ""),
# The sidebar panel
sidebar = dashboardSidebar(
# The sidebar manual
sidebarMenu(
id = "tabs",
# Tab 1
menuItem(
text = "Tab1",
tabName = "Tab1"
),
# Tab 2
menuItem(
text = "DT Example",
tabName = "DT_E"
)
)),
# The main panel
body = dashboardBody(
tabItems(
tabItem(
# The tab name
tabName = "Tab1",
h2("Placeholder")
),
# Tab 2: DT example
tabItem(
# The tab name
tabName = "DT_E",
h2("DT: Document the Input Values"),
sidebarPanel(
# The input widgets
sliderInput(inputId = "Slider", label = "The SliderInput", min = 1, max = 10, value = 5),
br(),
radioButtons(inputId = "Radio", label = "The RadioButtons", choices = c("A", "B", "C")),
br(),
textInput(inputId = "Text", label = "The TextInput", value = "Enter text ...")
),
# The datatable
DTOutput(outputId = "d1")
)
)
)
)
}
server <- function(input, output, session){
# Save the dat to a reactive object
dat_save <- reactiveValues(df = dat)
output$d1 <- renderDT(dat, options = list(pageLength = 5), editable = TRUE, rownames = TRUE)
outputOptions(output, "d1", suspendWhenHidden = FALSE)
# Save the condition of the data table d1
d1_proxy <- dataTableProxy("d1")
# Edit the data table in tab 3
observeEvent(input$d1_cell_edit, {
dat_save$df <- editData(dat_save$df, input$d1_cell_edit, d1_proxy)
})
# Update the input numbers for each cell
observeEvent(input$Slider, {
dat_save$df[1, "Value"] <- as.character(input$Slider)
})
observeEvent(input$Radio, {
dat_save$df[2, "Value"] <- input$Radio
})
observeEvent(input$Text, {
dat_save$df[3, "Value"] <- input$Text
})
observe({
replaceData(d1_proxy, dat_save$df, resetPaging = FALSE)
})
}
shinyApp(ui, server)
I am building an app with three segments:
Overview
Detailed results
Help
The detailed result section should show results of many sub-items, one at the time.
I am interested to the Result section to be a single tab, because I don't want to write code each tab for each sub-item. Each sub-item has identical, in the example a histogram.
When I run the example though, I loose the ID of the subitems.
Is it possible to have a layout like this but to keep the ID's of all menuitems and menusubitems?
Happy to look at alternative approaches.
An example to illustrate the issue is below. The solution will show the table in overview, a histogram in results for any of the sub-items and the HTML output in the help section.
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenu(id = "SideBarMENU",
menuItem("Overview", tabName = "OVERVIEW", selected = TRUE),
menuItem("Results", startExpanded = TRUE,
menuSubItem("Sepal.Length", tabName = "RESULTS"),
menuSubItem("Sepal.Width" , tabName = "RESULTS"),
menuSubItem("Petal.Length", tabName = "RESULTS"),
menuSubItem("Petal.Width" , tabName = "RESULTS")
),
menuItem("Help", tabName = "HELP")
)
),
dashboardBody(
tabItems(
tabItem("OVERVIEW",
box("Overview box",
tableOutput("overview"))
),
tabItem("RESULTS",
box("Results box",
plotOutput("results")
)
),
tabItem("HELP",
box("HELP box",
textOutput("help"))
)
)
)
)
server <- function(input, output, session) {
data <- reactive({
print(input$SideBarMENU)
if(input$SideBarMENU %in% names(iris)){
iris[[input$SideBarMENU]]
} else {
rnorm(100, 1000, 10)
}
})
output$results <- renderPlot({
hist(data())
})
output$overview <- renderTable({
head(iris)
})
output$help <- renderText({
HTML("A wiki is a website on which users collaboratively.....")
})
}
shinyApp(ui, server)
Basically, you need two components:
Dynamic content / plots
Dynamic dashboard body
The first part is more easy:
1. Dynamic content / plots
You can create the outputs in a loop as explained in a few other SO posts:
lapply(nms, function(name){
output[[name]] <- renderUI ({
box("Results Box", plotOutput(paste0("plot_", name)))
})
output[[paste0("plot_", name)]] <- renderPlot({
hist(iris[[input$SideBarMENU]], main = "")
})
})
2. Dynamic dashboard body
This part is more complicated. You need dynamic tabitems() and they have to be mixed with static parts. In order to hand over a list of tabitem() to tabitems() you can use do.call(tabItems, ..) for converting it, see the link below. To combine them with the static elements, convert the static ones as list() elements and combine them all in a list() before calling do.call(tabItems, ..).
output$tabItms <- renderUI ({
itemsDyn <- lapply(nms, function(name){
tabItem(tabName = name, uiOutput(name))
})
items <- c(
list(
tabItem("OVERVIEW",
box("Overview box",
tableOutput("overview"))
)
),
itemsDyn,
list(
tabItem("HELP",
box("HELP box",
textOutput("help"))
)
)
)
do.call(tabItems, items)
})
Similar components can be found here: shinydashboard does not work with uiOutput
and for looping tabItems() here: How to make a function in a for loop or lapply loop in a tabItem dashboard shiny.
Note:
I modify names(iris):
nms <- gsub("[.]", "", names(iris))
names(iris) <- nms
because no dots are allowed for the tabItem names.
Reproducible example:
library(shiny)
library(shinydashboard)
nms <- gsub("[.]", "", names(iris))
names(iris) <- nms
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
uiOutput("menu")
),
dashboardBody(
uiOutput("tabItms")
)
)
server <- function(input, output, session) {
output$tabItms <- renderUI ({
itemsDyn <- lapply(nms, function(name){
tabItem(tabName = name, uiOutput(name))
})
items <- c(
list(
tabItem("OVERVIEW",
box("Overview box",
tableOutput("overview"))
)
),
itemsDyn,
list(
tabItem("HELP",
box("HELP box",
textOutput("help"))
)
)
)
do.call(tabItems, items)
})
lapply(nms, function(name){
output[[name]] <- renderUI ({
box("Results Box", plotOutput(paste0("plot_", name)))
})
output[[paste0("plot_", name)]] <- renderPlot({
hist(iris[[input$SideBarMENU]], main = "")
})
})
output$menu <- renderUI({
sidebarMenu(id = "SideBarMENU",
menuItem("Overview", tabName = "OVERVIEW", selected = TRUE),
menuItem("Results", id = "resultChoice", startExpanded = TRUE,
lapply(nms, function(name) {
menuSubItem(name, tabName = name)
})
),
menuItem("Help", tabName = "HELP")
)
})
output$overview <- renderTable({
head(iris)
})
output$help <- renderText({
HTML("A wiki is a website on which users collaboratively.....")
})
}
shinyApp(ui, server)
I have looked everywhere and cant seem to find help with what must be a common issue.
I have a datatable in a shiny app. I load data into it when it first appears. It consists of one column of text
I want the user be able to press a button that takes the data in the datatable and performs an action on it and then presents a datatable with the result of that function. The function (not shown) basically splits the single column up into several columns.
I cant seem to figure out how to run a function from a button that refreshes and shows the new datatable.
This is what I have so far:
server.R
library(shiny)
library(EndoMineR)
RV <- reactiveValues(data = PathDataFrameFinalColon)
server <- function(input, output) {
output$mytable = DT::renderDT({
RV$data
})
output2$mytable = DT::renderDT({
RV$data<-myCustomFunction(RV$data)
})
}
ui.R
library(shiny)
basicPage(
fluidPage(
DT::dataTableOutput("mytable")
))
basically how do I allow a button on the page to run a specific function that then updates the datatable?
You can use observeEvent() and ignoreInit = TRUE so that the initial dataframe is rendered without the function being applied.
server <- function(input, output) {
RV <- reactiveValues(data = PathDataFrameFinalColon)
output$mytable = DT::renderDT({
RV$data
})
observeEvent(input$my_button,{
RV$data<-myCustomFunction(RV$data)
},ignoreInit = TRUE)
}
ui <- basicPage(
fluidPage(
DT::dataTableOutput("mytable"),
actionButton("my_button",label = "Run Function")
))
I hope this helps you. Have fun;
library(shiny)
library(shinydashboard)
dat = data.frame(id = c("d","a","c","b"), a = c(1,2,3,4), b = c(6,7,8,9))
header <- dashboardHeader(
)
sidebar <- dashboardSidebar(
tags$head(tags$style(HTML('.content-wrapper { height: 1500px !important;}'))),
sidebarMenu (
menuItem("A", tabName = "d1"),
menuItem("B", tabName = "d2"),
menuItem("C", tabName = "d3")
)
)
body <- dashboardBody(
tabItems(
tabItem(tabName = "d1",
box(title = "AAA",
actionButton("refreshTab1_id", "Refresh Tab 1"),
actionButton("sortTable1_id", "Sort Table 1"),
DT::dataTableOutput("table_for_tab_1", width = "100%"))
),
tabItem(tabName = "d2",
box(title = "BBB",
actionButton("refreshTab2_id", "Refresh Tab 2"),
actionButton("sortTable2_id", "Sort Table 2"),
DT::dataTableOutput("table_for_tab_2", width = "100%"))
),
tabItem(tabName = "d3",
box(title = "CCC",
actionButton("refreshTab3_id", "Refresh Tab 3"),
actionButton("sortTable3_id", "Sort Table 3"),
DT::dataTableOutput("table_for_tab_3", width = "100%"))
)
)
)
# UI
ui <- dashboardPage(header, sidebar, body)
# Server
server <- function(input, output, session) {
observe({
if (input$sortTable1_id || input$sortTable2_id || input$sortTable3_id) {
dat_1 = dat %>% dplyr::arrange(id)
} else {
dat_1 = dat
}
output$table_for_tab_1 <- output$table_for_tab_2 <- output$table_for_tab_3 <- DT::renderDataTable({
DT::datatable(dat_1,
filter = 'bottom',
selection = "single",
colnames = c("Id", "A", "B"),
options = list(pageLength = 10,
autoWidth = TRUE#,
# columnDefs = list(list(targets = 9,
# visible = FALSE))
)
)
})
})
observe({
if (input$refreshTab1_id || input$refreshTab2_id || input$refreshTab3_id) {
session$reload()
}
})
}
# Shiny dashboard
shiny::shinyApp(ui, server)
I'm trying to create a dashboard using Shiny. Here is some sample data:
###Creating Data
name <- c("Sharon", "Megan", "Kevin")
x <- c(5, 7,3)
y <- c(3,6,2)
z <- c(2,3,7)
jobForm = data.frame(name, x, y, z)
What I'm trying to figure out is, for every row of names how do I create their own TABLE? I believe there is a way to create a reactive for-loop but I've been at this for a long time and have given up.
Here is the full code of what the dashboard should look like for each name. This code only shows Sharon's scores, and it should run. If there are any issues on getting the code to run completely let me know.
I am using
packages shiny, shinydashboard and tidyverse
##Dashboard Header
header <- dashboardHeader(
title = "My Project")
##Dashboard Sidebar
sidebar <- dashboardSidebar(
sidebarMenu(
menuItem("Dashboard", icon = icon("dashboard"),tabName = "dashboard"),
menuItem("Job Positions", icon = icon("address-card"), tabName = "jobposition",
menuSubItem('Sales',
tabName = 'sales',
icon = icon('line-chart'))
)
)
)
##Dashboard Body
body <- dashboardBody(
tabItems(
# Dashboard Tab Content
tabItem(tabName = "dashboard",
fluidRow(
#Random Plot
box( )
)
),
# Associate Tab Content
tabItem(tabName = "sales",
fluidRow(
#Main Box for Candidate
box(
width = 8,
title = "Candidate 001",
status = "primary",
#Box for Table
box(
title = "Table",
status = "info",
tableOutput("stat1")
)
)
)
)
)
)
##User Interface Using Dashboard Function
ui <- dashboardPage(
skin = "yellow",
header,
sidebar,
body
)
##Server: Instructions
server <- function(input, output) {
temp <- data.frame(jobForm %>%
slice(1) %>%
select(x:z))
temp <- as.data.frame(t(temp))
output$stat1 <-renderTable({
temp
},
include.rownames=TRUE,
colnames(temp)<-c("Score")
)
}
##Create Shiny App Object
shinyApp(ui, server)
Thank you for any help
You better solve these kibnd of problems with an renderUI and since you never really know when shiny will evaluate an expression you are much better of using lapply then for loops.
name <- c("Sharon", "Megan", "Kevin")
x <- c(5, 7,3)
y <- c(3,6,2)
z <- c(2,3,7)
jobForm = data.frame(name, x, y, z)
##Dashboard Header
header <- dashboardHeader(
title = "My Project")
##Dashboard Sidebar
sidebar <- dashboardSidebar(
sidebarMenu(
menuItem("Dashboard", icon = icon("dashboard"),tabName = "dashboard"),
menuItem("Job Positions", icon = icon("address-card"), tabName = "jobposition",
menuSubItem('Sales',
tabName = 'sales',
icon = icon('line-chart'))
)
)
)
##Dashboard Body
body <- dashboardBody(
tabItems(
# Dashboard Tab Content
tabItem(tabName = "dashboard",
fluidRow(
#Random Plot
box( )
)
),
# Associate Tab Content
tabItem(tabName = "sales",
fluidRow(
#Main Box for Candidate
uiOutput("candidates")
)
)
)
)
##User Interface Using Dashboard Function
ui <- dashboardPage(
skin = "yellow",
header,
sidebar,
body
)
##Server: Instructions
server <- function(input, output) {
temp <- data.frame(jobForm %>%
slice(1) %>%
select(x:z))
temp <- as.data.frame(t(temp))
output$stat1 <-renderTable({
temp
},
include.rownames=TRUE,
colnames(temp)<-c("Score")
)
output$candidates <- renderUI(
tagList(
lapply(1:nrow(jobForm), function(idx){
output[[paste0("stat",idx)]] <- renderTable(
jobForm[idx,-1]
)
box(
width = 8,
title = paste0("Candidate: ",jobForm$name[idx]),
status = "primary",
#Box for Table
box(
title = "Table",
status = "info",
tableOutput(paste0("stat",idx))
)
)
})
)
)
}
##Create Shiny App Object
shinyApp(ui, server)
Hope this helps!!