简体   繁体   中英

How to add a unit conversion button to numericInput in a shiny app?

I am trying to build a shiny app in which users can provide a (numeric) parameter in different units. For this, I would like to have an input field to fill in the numeric value (eg like the one that the numericInput function provides) and two buttons (eg the buttons that the radioButtons function provides) in the same line, in which the user can specify which unit is used. It would look something like this example:

在此处输入图片说明

Ideally, the values of the min and max arguments in the numericInput depend on which unit is specified by the user. For example, the parameter creatinine can be provided in mg/dL and in umol/L where the conversion factor is 1 mg/dL = 88.42 umol/L and the allowed range would be 0.1 to 15 in mg/dL and 8.842 to 1326.3 in umol/L.

In addition to the dependency of min and max on the unit specified by the user, I would like to be able to make calculations with the numeric value ( creat in the example below) that - depending on the unit specified by the user - takes the conversion factor into account (eg with an if else construction in the server function).

Is this possible in shiny and if yes how would you do it in the below example?

library(shiny)

ui <- shinyUI(fluidPage(
  sidebarLayout(
    sidebarPanel(
      numericInput(inputId="creat",label="Creatinine",value="",min=0,max=15,)),   
    mainPanel(p('Some calculation with creatinine'),
      textOutput("creat"))
  )
))

server <- function(input, output) {
  output$creat <- renderText({input$creat*100})
}

shinyApp(ui = ui, server = server)

Many thanks in advance!

Perhaps this will meet your needs.

library(shiny)

ui <- shinyUI(fluidPage(
  tags$head(
    tags$style(HTML("
  #creat {
    width: 110px;
  }
"))),
  tags$head( tags$style(type="text/css","label{ display: table-cell; text-align: center;vertical-align: middle; } .form-group { display: table-row;}") ),
  sidebarLayout(
    sidebarPanel(
      div(style= "display: inline;",
        numericInput(inputId="creat",label="Creatinine ",value="",min=0.1,max=15,step=0.1, width = "80px")),
      div(style= "display: inline;",
          awesomeRadio(
            inputId = "units",
            label = "",
            choices = list("mg/dl" = "mg", "umol/L" = "um"),
            selected = "mg",
            inline = TRUE,
            status = "success",
            width = "300px"
          )
      )
      ),
    mainPanel(p('Some calculation with creatinine'), verbatimTextOutput("value"),
              textOutput("creat"))
  )
))

server <- function(input, output, session) {
  output$creat <- renderText({input$creat})
  
  numbers <- reactive({
    if (input$units=="um"){ 
      minval <- 8.842
      maxval <- 1326.3
    }else {
      minval <- 0.1
      maxval <- 15
    }
    validate(
      need(is.numeric(input$creat) & input$creat >= minval & input$creat <= maxval , sprintf("Please input a number between %s to %s", minval,maxval))
    )
  })
  output$value <- renderPrint({ numbers() })

  observeEvent(input$units,{
    print(input$units)
    if (input$units=="um"){
      if (is.null(input$creat)) value <- NULL
      else value <- input$creat*88.42
      
      updateNumericInput(
        session = session, # getDefaultReactiveDomain(),
        inputId = "creat",
        value = value,
        min = 8.842,
        max = 1326.3,
        step = 0.1
      )
    }else if (input$units=="mg") {
      if (is.null(input$creat)) value <- NULL
      else value <- input$creat/88.42
      
      updateNumericInput(
        session = session, # getDefaultReactiveDomain(),
        inputId = "creat",
        value = value,
        min = 0.1,
        max = 15,
        step = 0.1
      ) 
    }
    
  })
}

shinyApp(ui = ui, server = server)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM