Yvonnick Noel
Yvonnick Noel

Reputation: 51

Using textInput both as input and output fields in shiny

I am new to Shiny but already find it most interesting fo rapid GUI development.

I am trying to get the following: I basically have two textInputs. When the first is changed, I would like the second one to be automatically updated with some new value (not using any actionButton), and the other way around too. But I am getting an infinite loop.

A simple example where updating means adding one is:

server.r

library(shiny)

shinyServer(function(input, output,session) {

  observe({
    newval = as.numeric(input$field1)+1
    updateTextInput(session,"field2",value=newval)
  })

  observe({
    newval = as.numeric(input$field2)+1
    updateTextInput(session,"field1",value=newval)
  })
})

ui.R

library(shiny)   

shinyUI(basicPage(

    textInput("field1", "Field 1", ""),
    textInput("field2", "Field 2", "")

))

I tried to encapsulate 'input$field1' and 'input$field2' within a call to isolate() but this does not solve the problem.

Any suggestion? Many thanks in advance,

Yvonnick

Upvotes: 0

Views: 1734

Answers (1)

Yvonnick Noel
Yvonnick Noel

Reputation: 51

Just in case someone encounters a similar problem, I finally found the following solution, using boolean reactive values as flags for activating/blocking text input updates.

ui.R

library(shiny)   

shinyUI(basicPage(

  textInput("value1", "Value 1", ""),
  textOutput("value1TRUE"),
  textInput("value2", "Value 2", ""),
  textOutput("value2TRUE")
))

server.R

library(shiny)

shinyServer(function(input, output,session) {

  myVals = reactiveValues(changeValue1=TRUE,changeValue2=TRUE)

  observe({
    if( (input$value1=="") || is.na(input$value1) ) return(NULL)
    isolate({
      if(!myVals$changeValue2) {
        myVals$changeValue2 = TRUE
        return(NULL)
      }
      myVals$changeValue1 = FALSE
      updateTextInput(session,"value2",value=as.numeric(input$value1)+1)
    })
  })

  observe({
    if( (input$value2=="") || is.na(input$value2) ) return(NULL)
    isolate({
      if(!myVals$changeValue1) {
        myVals$changeValue1 = TRUE
        return(NULL)
      }
      myVals$changeValue2 = FALSE
      updateTextInput(session,"value1",value=as.numeric(input$value2)+1)
    })
  })

  output$value1TRUE = renderText(as.character(myVals$changeValue1))
  output$value2TRUE = renderText(as.character(myVals$changeValue2))
})

If some shiny guru finds a lighter solution, I'd be interested to know about it :-)

Best, Yvonnick

Upvotes: 2

Related Questions