RinteRface / shinyMobile

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

updateF7Select choices #242

Open grcatlin opened 1 year ago

grcatlin commented 1 year ago

In #45, it's brought up that updateF7Select does not allow for choices to be changed. After playing around with this, I've determined that there's a simple enough fix for this - changing the class of the tags$select() within the f7Select function.

Before:

f7Select = function (inputId,
          label,
          choices,
          selected = NULL,
          width = NULL)
{
  options <- createSelectOptions(choices, selected)
  shiny::tags$div(
    class = "list",
    style = if (!is.null(width))
      paste0("width:", htmltools::validateCssUnit(width),
             ";"),
    shiny::tags$ul(
      shiny::tags$li(
        class = "item-content item-input",
        shiny::tags$div(
          class = "item-inner",
          shiny::tags$div(class = "item-title item-label",
                          label),
          shiny::tags$div(
            class = "item-input-wrap input-dropdown-wrap",
            shiny::tags$select(
              class = "input-select",
              id = inputId,
              placeholer = "Please choose...",
              options
            )
          )
        )
      )
    )
  )
}

All that is necessary is to modify the class = "input-select" to class = "form-control":

function (inputId,
          label,
          choices,
          selected = NULL,
          width = NULL)
{
  options <- createSelectOptions(choices, selected)
  shiny::tags$div(
    class = "list",
    style = if (!is.null(width))
      paste0("width:", htmltools::validateCssUnit(width),
             ";"),
    shiny::tags$ul(
      shiny::tags$li(
        class = "item-content item-input",
        shiny::tags$div(
          class = "item-inner",
          shiny::tags$div(class = "item-title item-label",
                          label),
          shiny::tags$div(
            class = "item-input-wrap input-dropdown-wrap",
            shiny::tags$select(
              class = "form-control",
              id = inputId,
              placeholer = "Please choose...",
              options
            )
          )
        )
      )
    )
  )
}

From there, you can use shiny's normal updateSelectInput function instead of updateF7Select and it works as expected. Here is a minimal example:

if (interactive()) {
  library(shiny)
  library(shinyMobile)

  f7Select_Alt = function (inputId,
                           label,
                           choices,
                           selected = NULL,
                           width = NULL) {
    options <- shinyMobile:::createSelectOptions(choices, selected)
    shiny::tags$div(
      class = "list",
      style = if (!is.null(width))
        paste0("width:", htmltools::validateCssUnit(width),
               ";"),
      shiny::tags$ul(
        shiny::tags$li(
          class = "item-content item-input",
          shiny::tags$div(
            class = "item-inner",
            shiny::tags$div(class = "item-title item-label",
                            label),
            shiny::tags$div(
              class = "item-input-wrap input-dropdown-wrap",
              shiny::tags$select(
                class = "form-control",
                id = inputId,
                placeholer = "Please choose...",
                options
              )
            )
          )
        )
      )
    )
  }

  choices = c("a", "b", "c")
  updated_choices = c(1:3)

  shinyApp(
    ui = f7Page(
      title = "My app",
      f7SingleLayout(
        navbar = f7Navbar(title = "Update f7Select Choices"),
        f7Select("normal", "f7Select", choices, "a"),
        f7Select_Alt("alt", "f7Select_Alt", choices, "a"),
        f7Button("update_normal",
                 "Update f7Select (this will crash the app)"),
        f7Button("update_alt", "Update f7Select_Alt"),
      )
    ),
    server = function(input, output, session) {
      observeEvent(input$update_normal, {
        updateF7Select("normal", choices = updated_choices, selected = 1)
      })
      observeEvent(input$update_alt, {
        updateSelectInput(session,
                          "alt",
                          choices = updated_choices,
                          selected = 1)
      })
    }
  )
}
khbrc commented 1 year ago

Thanks heaps. I appreciate the fix.

lavaman13 commented 1 month ago

Thanks for this fix, works great!