'Can't get correct behaviour with R Shiny numericInput fields that have some dependencies

In a month I spend on items A and B. All other spending falls under, “anything_else”. monthly_spending is always the total of (a + b + anything_else)

Any field can be manually set by the user subject to the rules below.

There are some rules mentioned that I can’t get to work.

Below, I’ve noted the rule and whether it is working or not.


Rules

monthly_spending field

  1. Not working

Rule: monthly_spending is always sum(a+ b + anything_else)

Fail: Can’t manually enter a number in the anything_else field and have monthly_spending reflect the sum of (a + b + anything_else)

  1. Working

Rule: As monthly_spending decreases/increases (using arrows), so does anything_else.

  1. Not Working

Rule: As monthly_spending decreases/increases by manually entering a number, so does anything_else.

Fail: Can’t manually enter a number in the monthly_spending field

  1. Working

Rule: monthly_spending can never go lower than sum(a + b)

a, b fields

  1. Working

Rule: As a, or b increase, anything_else decreases until 0. Then, monthly_spending increases

anything_else field

  1. Not working

Rule: When anything_else decreases/increases then monthly_spending always decreases/increases

library("shiny")
library("bslib")
library("shinyWidgets")

per_month <- "/mth"

ui <- bootstrapPage(
  # https://bootswatch.com/journal/
  theme = bs_theme(version = 5, "font_scale" = 1.0), 
  div(class = "container-fluid",
      
      div(class = "row",
          div(class="col-4", 
              numericInputIcon(
                inputId = "monthly_spending",
                label = "monthly_spending",
                value = 1000,
                min = 0,
                max = 9000,
                width = "160px",
                icon = list(NULL, per_month)
              ),
          ),
          div(class="col-4", 
              numericInputIcon(
                inputId = "a",
                label = "A",
                value = 200,
                min = 0,
                max = 9000,
                width = "160px",
                icon = list(NULL, per_month)
              ),
          ),
          div(class="col-4", 
              numericInputIcon(
                inputId = "b",
                label = "B",
                value = 50,
                min = 0,
                max = 9000,
                width = "160px",
                icon = list(NULL, per_month)
              ),
          ),
          div(class="col-4", 
              numericInputIcon(
                inputId = "anything_else",
                label = "anything_else",
                value = 0,
                min = 0,
                max = 9000,
                width = "160px",
                icon = list(NULL, per_month)
              ),
          )
      )
  )
)

server <- function(input, output, session) {
  observe({
    anything_else <- input$monthly_spending - sum(c(input$a, input$b))
    if(anything_else < 0){
      # Update monthly_spending and reset any to zero
      freezeReactiveValue(input, "monthly_spending")
      updateNumericInputIcon(
        session = session,
        inputId = "monthly_spending",
        value = sum(c(input$a, input$b))
      )
      freezeReactiveValue(input, "anything_else")
      updateNumericInputIcon(
        session = session,
        inputId = "anything_else",
        value = 0
      )
    } else {
      # Update anything_else
      freezeReactiveValue(input, "anything_else")
      updateNumericInputIcon(
        session = session,
        inputId = "anything_else",
        value = anything_else
      )
    }
  })

}

shinyApp(ui, server)


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source