RinteRface / shinyMobile

shiny API for Framework7 (IOS/android)
https://shinymobile.rinterface.com
406 stars 74 forks source link

Is it possible to use validateF7Input() on an input rendered on the server using renderUI() ? #251

Open frasemcl opened 10 months ago

frasemcl commented 10 months ago

I'm facing an issue while trying to apply validateF7Input() to an input generated dynamically on the server using renderUI().

For inputs in the UI from the start, the validateF7Input() works as expected by using the following code in the server:

observe({
  validateF7Input(
    inputId = ns("my_example_id"),
    pattern = "^\\d*\\.?\\d+$", # regex for int or float
    error = "Please enter a number"
  )
})

However, I've encountered difficulties getting it to work for the following input created on the server, which is conditionally shown based on another input:

observeEvent(input$flowmeasured, {
  if (input$flowmeasured == "Yes"){
    x = f7Text(
      inputId = ns("conditional_input"),
      label = "Depth (cm):"
      # value = '0.0'
    )
  } else {
    x = ""
  }
  output$veriflow_srv <- renderUI({
    x %||% ""
  })
})

I tried running observe() only after the same condition changes, but it doesn't seem to enable validateF7Input() for the dynamically generated input:

observeEvent(input$flowmeasured, {
  if (input$flowmeasured == "Yes"){
    observe({
      validateF7Input(
        inputId = ns("conditional_input"),
        pattern = "^\\d*\\.?\\d+$", # regex for int or float
        error = "Please enter a number"
      )
    })
  }
})

Then I tried the same thing within a reactive function, but still no dice:

  addNewValidators <- reactive({
    if (input$flowmeasured == "Yes") {
      validateF7Input(
        inputId = ns("conditional_input"),
        pattern = "^\\d*\\.?\\d+$", # regex for int or float
        error = "Please enter a number"
      )
    }
  })
  observe({
    addNewValidators()
  })

I'm seeking guidance or suggestions on how to effectively use validateF7Input() for inputs generated dynamically on the server. Any insights would be greatly appreciated. Thank you!

frasemcl commented 10 months ago

Update on this, I got it working well enough by using an if statement at the start of my observe block, but I could still use some help if anyone has suggestions. Since input$conditional_input1,2and3 only exists if user answers 'Yes' to a previous input, the following works pretty well, but I'm sure there is a more elegant way to achieve this:

    observe({
      # Thought that req() would work but ended up working better with subsequent if statement
      # req(input$conditional_input1)
      if (!isTruthy(input$conditional_input1) && !isTruthy(input$conditional_input2) && !isTruthy(input$conditional_input3)) {
      print('conditionally running')
      lapply(c("conditional_input1", "conditional_input2", "conditional_input3", function(n) {
        observe({
          validateF7Input(
            inputId = ns(n),
            pattern = "^\\d*\\.?\\d+$", # regex for int or float
            error = "Please enter a number"
          )
        })
      }
      )
      }
    })

Apologies that this example or the examples above aren't given in a demo shiny app.

frasemcl commented 9 months ago

Thx for your consideration. FYI for my use case I ended up going with your radio input combined with shinyjs show() and hide() and that seems to be working well so far. I decided the falsy check above and the observe() within observe() was too hard to reason about and the input warnings weren't working perfectly.