Home > other >  Is there a way to capture whether any radio button has been clicked and react from it
Is there a way to capture whether any radio button has been clicked and react from it

Time:04-19

please refer to the reproducible code below. Everything works fine up to one point. If you select a team, and choose a weight through pushing the action buttons, and then click the populate button, a table appears with the weights.

One thing though. If you select, say team = a, and input 10%, and switch to team = b. The input is still at 10%. I'd like it to revert back to 0 so you always start anew.

Anyway to do this?

library(shiny)

library(dplyr)
library(shinydashboard)
library(shinydashboardPlus)
library(shinyWidgets)

df = data.frame(team = c("a", "b", "c", "d"),
                weights = c(0, 0, 0, 0))
df

ui = dashboardPage(
  header = dashboardHeader(title = "teams"),
  sidebar = dashboardSidebar(),
  body = dashboardBody(
    prettyRadioButtons(
      inputId = "radio1",
      label = "Select Teams",
      choices = df$team
    ),
    br(),

div(style = "margin-top: 10px;width: 100px; display: inline-block", textOutput("text1a")),
div(
  style = "width: 25px; display: inline-block; margin-left: 1px",
  actionBttn(
    inputId = "action1a",
    size = "xs",
    label = "-",
    style = "material-flat",
    color = "primary"
  )
),
div(style = "width: 25px; display: inline-block; margin-left: 10px; text-align: center", textOutput("text1b")),
div(
  style = "width: 25px; display: inline-block; margin-left: 25px",
  actionBttn(
    inputId = "action1b",
    size = "xs",
    label = " ",
    style = "material-flat",
    color = "primary"
  )
),
br(),
br(),

actionBttn(
  inputId = "populate",
  size = "xs",
  label = "Populate Weights",
  style = "material-flat",
  color = "danger"
),
br(),
br(),
div(style = "width: 800px; margin-left: 10px", tableOutput("table1"))
   ))  # End of Dashboard Body and Page

server = function(input, output, session) {
  rv = reactiveValues(action1 = 0, df = df)
  
  output$text1a = renderText(paste("Team", input$radio1, sep = " "))
  
  rv$action1 = eventReactive(c(input$action1a, input$action1b),
                             {
                               min(max(-5 * input$action1a   5 * input$action1b,-50),50)
                             })
  
  output$text1b = renderText({
    if (rv$action1() >= 0) {
      paste(" ", rv$action1(), sep = "")
    }
    else {
      rv$action1()
    }
  })
  
  rv$df = eventReactive(
    input$populate,
    df <<- rbind(
      df %>% filter(team == input$radio1) %>% mutate(weights = rv$action1()),
      df %>% filter(team != input$radio1)
    ) %>% arrange(team)
  )

  output$table1 = renderTable({
    rv$df()
  }) 
}

shinyApp(ui = ui,
         server = server,
         options = list(launch.browser = T))

CodePudding user response:

below is my interpretation of what you want. I put the info in the code too, but I'll give a brief idea here. Rather than use eventReactive, I used reactiveValues. This way I have a number that I can alter with different inputs. I then used observeEvent on each of the three inputs, radio1, action1a, and action1b. If any button on radio1 is pressed, the reactiveValues is set to 0. If action1a is pressed, minus five from the reactiveValues, and of course add 5 if action1b is pressed.

library(dplyr)
library(shiny) #Added the library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(shinyWidgets)

df = data.frame(team = c("a", "b", "c", "d"),
                weights = c(0, 0, 0, 0))
df

ui = dashboardPage(
  header = dashboardHeader(title = "teams"),
  sidebar = dashboardSidebar(),
  body = dashboardBody(
    prettyRadioButtons(
      inputId = "radio1",
      label = "Select Teams",
      choices = as.character(df$team)
    ),
    br(),
    
    div(style = "margin-top: 10px;width: 100px; display: inline-block", textOutput("text1a")),
    div(
      style = "width: 25px; display: inline-block; margin-left: 1px",
      actionBttn(
        inputId = "action1a",
        size = "xs",
        label = "-",
        style = "material-flat",
        color = "primary"
      )
    ),
    div(style = "width: 25px; display: inline-block; margin-left: 10px; text-align: center", textOutput("text1b")),
    div(
      style = "width: 25px; display: inline-block; margin-left: 25px",
      actionBttn(
        inputId = "action1b",
        size = "xs",
        label = " ",
        style = "material-flat",
        color = "primary"
      )
    ),
    br(),
    br(),
    
    actionBttn(
      inputId = "populate",
      size = "xs",
      label = "Populate Weights",
      style = "material-flat",
      color = "danger"
    ),
    br(),
    br(),
    div(style = "width: 800px; margin-left: 10px", tableOutput("table1"))
  ))  # End of Dashboard Body and Page

server = function(input, output, session) {
  rv = reactiveValues(action1 = 0, df = df)
  
  output$text1a = renderText(paste("Team", input$radio1, sep = " "))
  
  DF<-reactiveValues("DF" = 0) #Using a reactiveValue instead of eventreactive
  
  observeEvent(input$action1a,{ #Observe's action 1a. When pressed, take the current reactiveValue DF$DF, and -5
    temp<-isolate(DF$DF)
    DF$DF<-temp-5
  })
  
  observeEvent(input$action1b,{ #Observe's action 1b. When pressed, take the current reactiveValue DF$DF, and  5
    temp<-isolate(DF$DF)
    DF$DF<-temp 5
  })
  
  observeEvent(input$radio1,{ #Observe's radio1. If this button is changed, reset reactiveValue to 0. 
    DF$DF<-0
  })
  
  
  output$text1b = renderText({ #Rendertext only displays the reactiveValue
    DF$DF
  })
  
  rv$df = eventReactive(
    input$populate,
    df <<- rbind(
      df %>% filter(team == input$radio1) %>% mutate(weights = DF$DF), #Changed weights to be the reactiveValues
      df %>% filter(team != input$radio1)
    ) %>% arrange(team)
  )
  
  
  output$table1 = renderTable({
    rv$df()
  }) 
}

shinyApp(ui = ui,
         server = server,
         options = list(launch.browser = T))

As I switched from eventReactive, I can see this not being the ideal solution, but this is how I would accomplish what you are doing. An alternate idea is to use shinyjs, which can reset certain inputs, though I'm not sure it would work with your original code as it may not reset an eventReactive. Best of luck, I hope this helps!

  • Related