numericInput で制限値を超える値が入力できてしまうバグへの対応

本日は、numericInputという数字を入力するUIパーツのバグの話です。

numericInputで出てくるスピンをクリックして入力している間はmax, minで指定した範囲を超える入力ができないように
なっていますが、BOXに直接入力すると指定範囲を超えていても値が反映されてしまいます。

困ったことにnumericInputのようなreactiveパーツは入力結果が即他の参照部分に波及するので
対応処理を加えておかないとエラーなど思わぬ動きの原因になります。

基本は入力数値を利用する際に処理を加えることになるかと思いますが、ここでは入力BOX直後のプロセスを修正して
範囲外の入力値を受け付けないようにする方法
を紹介します。

結果は以下のサンプルコードを見てもらえばわかるとおもいますが、
numericInputで入力された値を直接は使わずに、範囲チェック(CAPロジック)を入れている点がポイントです。
その後の処理はCAPチェックをかけた後のoutValue()を利用して各種処理が行えます。
注意点としては、numericInputから得た値(以下の例では、input$testInput)や`outValue()はreactive環境でのみ利用可能なので、
observe( )やreactive( )などの中で使う必要がある点です。

library(shiny)
ui <- fluidPage(
column(width=6,
numericInput(inputId = "testInput", label = "Test Input",
value = 70, min = 0, max = 100, step = 1,
width = "50%"
),
#CAP後の入力結果の出力
verbatimTextOutput("newValue")
)
)
server <- function(session, input, output) {
#上下CAPを適用するロジック
outValue = reactive({
if(input$testInput > 100) return(100)
else if(input$testInput <   0) return(  0)
else return(input$testInput)
})
#CAP後の値を出力BOXに描画:その後のプログラムではこのoutValue値を利用すればよい。
output$newValue <- renderText({ outValue() })
#CAP後の値を入力ボックスにUpdate
observe({
updateNumericInput(session=session, inputId = "testInput",
value = outValue())
})
}
shinyApp(ui, server)

もしくはserver部分は一連の処理をobserve( )で囲んでも同じ挙動となります。この場合はoutValueobserve( )の中で
作成した変数なので上記とは異なり変数の後に( )がなくてもOKです。

server <- function(session, input, output) {
observe({
if(input$testInput > 100) {
outValue = 100
} else if(input$testInput <   0) {
outValue =  0
} else {
outValue = input$testInput
}
updateNumericInput(session=session, inputId = "testInput",
value = outValue)
output$newValue <- renderText({ outValue })
})
}