Date: 2024-10-04

# Inputs Layout and Forms

#### 2024-10-04

Since {shinyMobile} 2.0.0, the layout of inputs has been improved. It is recommended that multiple inputs are wrapped inside a `f7List()` to benefit from styling options such as `inset`, `strong`, `dividers`,and `outline`. Also introduced since 2.0.0 are the functions `f7Form()` and `updateF7Form()` to gather inputs in the same form and update them in batch or only selected ones.

## Inputs Layout

In your app you can have many different inputs. Most of the time these inputs are nicely displayed together so the users can make her/his selections. With the many styling options that Framework7 provides, it can be quite a hassle if you would have to style them all individually. Luckily, you don’t have to! You can wrap them inside a `f7List()` to benefit from the styling options, styling them all at once (see below with the iOS skin):

Code

    library(shiny)
    library(shinyMobile)

    shinyApp(
      ui = f7Page(
        options = list(dark = FALSE, theme = "ios"),
        title = "Inputs Layout",
        f7SingleLayout(
          navbar = f7Navbar(
            title = "Inputs Layout",
            hairline = FALSE
          ),
          f7List(
            inset = TRUE,
            dividers = TRUE,
            strong = TRUE,
            outline = FALSE,
            f7Text(
              inputId = "text",
              label = "Text input",
              value = "Some text",
              placeholder = "Your text here"
            ),
            f7TextArea(
              inputId = "textarea",
              label = "Text area input",
              value = "Some text",
              placeholder = "Your text here"
            ),
            f7Select(
              inputId = "select",
              label = "Make a choice",
              choices = 1:3,
              selected = 1
            ),
            f7AutoComplete(
              inputId = "myautocomplete",
              placeholder = "Some text here!",
              openIn = "dropdown",
              label = "Type a fruit name",
              choices = c(
                "Apple", "Apricot", "Avocado", "Banana", "Melon",
                "Orange", "Peach", "Pear", "Pineapple"
              )
            ),
            f7Toggle(
              inputId = "toggle",
              label = "Toggle me"
            ),
            f7Picker(
              inputId = "picker",
              placeholder = "Some text here!",
              label = "Picker Input",
              choices = c("a", "b", "c"),
              options = list(sheetPush = TRUE)
            ),
            f7DatePicker(
              inputId = "date",
              label = "Pick a date",
              value = Sys.Date()
            ),
            f7ColorPicker(
              inputId = "mycolorpicker",
              placeholder = "Some text here!",
              label = "Select a color"
            )
          )
        )
      ),
      server = function(input, output) {
      }
    )

By default inputs list is displayed with stacked labels. Stacked labels always appear on top of the input.

The following inputs are supported:

- `f7Text()`
- `f7TextArea()`
- `f7Password()`
- `f7Select()`
- `f7SmartSelect()`
- `f7AutoComplete()`
- `f7Stepper()`
- `f7Toggle()`
- `f7Picker()`
- `f7DatePicker()`
- `f7ColorPicker()`

This doesn’t mean you can’t use other inputs, but they may look a bit off. In this case you can take them out of `f7List()` and style them manually with the available options in the input. For example, `f7CheckboxGroup()` and `f7Radio()` are not supported in `f7List()` but can be styled to look similar:

Code

    library(shiny)
    library(shinyMobile)

    shinyApp(
      ui = f7Page(
        options = list(dark = FALSE, theme = "ios"),
        title = "Inputs Layout",
        f7SingleLayout(
          navbar = f7Navbar(
            title = "Inputs Layout",
            hairline = FALSE
          ),
          f7List(
            inset = TRUE,
            dividers = TRUE,
            strong = TRUE,
            outline = FALSE,
            f7Text(
              inputId = "text",
              label = "Text input",
              value = "Some text",
              placeholder = "Your text here"
            ),
            f7TextArea(
              inputId = "textarea",
              label = "Text area input",
              value = "Some text",
              placeholder = "Your text here"
            ),
            f7Select(
              inputId = "select",
              label = "Make a choice",
              choices = 1:3,
              selected = 1
            ),
            f7AutoComplete(
              inputId = "myautocomplete",
              placeholder = "Some text here!",
              openIn = "dropdown",
              label = "Type a fruit name",
              choices = c(
                "Apple", "Apricot", "Avocado", "Banana", "Melon",
                "Orange", "Peach", "Pear", "Pineapple"
              )
            ),
            f7Stepper(
              inputId = "stepper",
              label = "My stepper",
              min = 0,
              color = "default",
              max = 10,
              value = 4
            ),
            f7Toggle(
              inputId = "toggle",
              label = "Toggle me"
            ),
            f7Picker(
              inputId = "picker",
              placeholder = "Some text here!",
              label = "Picker Input",
              choices = c("a", "b", "c"),
              options = list(sheetPush = TRUE)
            ),
            f7DatePicker(
              inputId = "date",
              label = "Pick a date",
              value = Sys.Date()
            ),
            f7ColorPicker(
              inputId = "mycolorpicker",
              placeholder = "Some text here!",
              label = "Select a color"
            )
          ),
          f7CheckboxGroup(
            inputId = "checkbox",
            label = "Checkbox group",
            choices = c("a", "b", "c"),
            selected = "a",
            style = list(
              inset = TRUE,
              dividers = TRUE,
              strong = TRUE,
              outline = FALSE
            )
          ),
          f7Radio(
            inputId = "radio",
            label = "Radio group",
            choices = c("a", "b", "c"),
            selected = "a",
            style = list(
              inset = TRUE,
              dividers = TRUE,
              strong = TRUE,
              outline = FALSE
            )
          )
        )
      ),
      server = function(input, output) {
      }
    )

## Forms

Since {shinyMobile} 2.0.0, the functions `f7Form()` and `updateF7Form()` have been introduced to gather inputs in the same form and update them in batch or only selected ones. The form returns a list with all the inputs inside it, and you can access them by their `inputId`.

In the below example this means you can gather all the values by simply calling `input$myform` and update them all at once by calling `updateF7Form()`:

Code

    library(shiny)
    library(shinyMobile)

    shinyApp(
      ui = f7Page(
        f7SingleLayout(
          navbar = f7Navbar(title = "Inputs form"),
          f7Block(f7Button("update", "Click me")),
          f7BlockTitle("A list of inputs in a form"),
          f7List(
            inset = TRUE,
            dividers = FALSE,
            strong = TRUE,
            outline = FALSE,
            f7Form(
              id = "myform",
              f7Text(
                inputId = "text",
                label = "Text input",
                value = "Some text",
                placeholder = "Your text here",
                style = list(
                  description = "A cool text input",
                  outline = TRUE,
                  media = f7Icon("house"),
                  clearable = TRUE,
                  floating = TRUE
                )
              ),
              f7TextArea(
                inputId = "textarea",
                label = "Text Area",
                value = "Lorem ipsum dolor sit amet, consectetur
                  adipiscing elit, sed do eiusmod tempor incididunt ut
                  labore et dolore magna aliqua",
                placeholder = "Your text here",
                resize = TRUE,
                style = list(
                  description = "A cool text input",
                  outline = TRUE,
                  media = f7Icon("house"),
                  clearable = TRUE,
                  floating = TRUE
                )
              ),
              f7Password(
                inputId = "password",
                label = "Password:",
                placeholder = "Your password here",
                style = list(
                  description = "A cool text input",
                  outline = TRUE,
                  media = f7Icon("house"),
                  clearable = TRUE,
                  floating = TRUE
                )
              ),
              f7Select(
                inputId = "select",
                label = "Select a number",
                choices = c(1, 2, 3),
                style = list(
                  description = "A selection",
                  outline = TRUE,
                  media = f7Icon("house")
                )
              )
            )
          ),
          f7Block(verbatimTextOutput("form"))
        )
      ),
      server = function(input, output, session) {
        output$form <- renderPrint(input$myform)

        observeEvent(input$update, {
          updateF7Form(
            "myform",
            data = list(
              "text" = "New text",
              "textarea" = "New text area",
              "password" = "New password",
              "select" = 3
            )
          )
        })
      }
    )

Since the `f7Form()` is wrapped inside a `f7List()`, it will look like a regular list of inputs. The difference is in the way the inputs are gathered and how they can be updated.

Currently, the following inputs supported for the form are:

- `f7Text()`
- `f7TextArea()`
- `f7Password()`
- `f7Select()`

Having other types of inputs in your form might not looks as good, or it might not return the expected results.