Reputation: 999
# ui.R
shinyUI(
fluidPage(
titlePanel("Make a data frame and display"),
fluidRow(column(4,selectInput('types', 'Select the type',c("Basketball","Soccer")))),
uiOutput('typeChange'),
mainPanel(dataTableOutput('displayDf'))
)
)
I am trying to take a user input and store the data in to a data frame. I then want to display the data frame simultaneously as the user keeps on adding records. The above code lets user select between Basketball and Soccer
# server.R
# Create a function to initiate and clear global variables
clear_all <- function(){
z <<- c()
z1 <<- c()
z2 <<- c()
z3 <<- c()
}
clear_all()
shinyServer(function(input, output, session) {
# make additional ui depending on the sport selected.
output$typeChange <- renderUI({
if (input$types=="Basketball"){
clear_all()
fluidRow(
column(4,textInput("v1","Player name")),
column(4,selectInput("v2", "Age:",c("20","25","30"))),
column(4,actionButton("add", "Add the above player")))
}else if (input$types=="Soccer"){
clear_all()
fluidRow(
column(4,textInput("v1","Player name")),
column(4,selectInput("v2", "Age",c("20","25","30"))),
column(4,selectInput("v3", "Income:",c("100","125","150"))),
column(4,actionButton("add", "Add the above player")))
}else{}
})
# if a user adds a player, update the dataframe and display
observeEvent(input$add, {
if (input$types=="Basketball"){
z1 <<- c(z1,input$v1)
z2 <<- c(z2,input$v2)
z<<- data.frame(Player=z1,Age=z2)
}else if (input$types=="Soccer"){
z1 <<- c(z1,input$v1)
z2 <<- c(z2,input$v2)
z3 <<- c(z3,input$v3)
z<<- data.frame(Player=z1,Age=z2,Income=z3)
}
output$displayDf=renderDataTable(z)
})
})
The server side code creates new text and selectinput depending on what sport is selected. The functionality I am trying to create is that after selecting a sport, a user can enter the other inputs and add the player. The list of players a user added should be displayed as long as the user doesn't select a different sport. Once the user changes the sport, the data frame will be empty and nothing from the previous sport should be displayed.
The issue that I am facing is that if I add 3 players in basketball and then change my top selection to soccer, i still see the basketball data until i add a soccer player. I want the displayed data frame to hide as soon as I change the sport. Also attached are the screenshots of the same.Please advise.
Upvotes: 1
Views: 1677
Reputation: 6155
Your problem can be solved if you put the datatable in a reactive Output, so that it's always displaying what input$type
says, that is:
tables
which has length 2 and stores tables for basketball and soccer, respectively.input$type
show one or the other.I tidied your app while solving this (1. don't use duplicate input IDs, 2. using global variables is not as clean as using the reactives, 3. Use conditionPanels):
library(shiny)
library(plotly)
library(shinyjs)
ui <- shinyUI(
fluidPage(
useShinyjs(),
titlePanel("Make a data frame and display"),
fluidRow(column(4,selectInput('types', 'Select the type',c("Basketball","Soccer")))),
fluidRow(column(width=8,
column(4, textInput("v1","Player name")),
column(4, selectInput("v2", "Age:",c("20","25","30"))),
conditionalPanel(condition="input.types == 'Soccer'",
column(4, selectInput("v3", "Income:",c("100","125","150"))))),
column(1, actionButton("add", "Add the above player"))),
mainPanel(dataTableOutput('displayDf'))
)
)
server <- shinyServer(function(input, output, session) {
tables <- reactiveValues(basketball = data.frame(Player = character(), Age = numeric()),
soccer = data.frame(Player = character(), Age = numeric(), Income = double()))
# if a user adds a player, update the dataframe and display
observeEvent(input$add, {
if (input$types=="Basketball"){
oldVals <- tables$basketball
tables$basketball <- rbind(oldVals, data.frame(Player = input$v1, Age = input$v2))
}else if (input$types=="Soccer"){
oldVals <- tables$soccer
tables$soccer <- rbind(oldVals, data.frame(Player = input$v1, Age = input$v2, Income = input$v3))
}
# reset the input values
reset("v1")
reset("v2")
reset("v3")
})
# display the appropriate table
output$displayDf <- renderDataTable({
if (input$types=="Basketball") tables$basketball else tables$soccer
})
})
shinyApp(ui, server)
Upvotes: 2