Skip to content

Best way to integrate other input methods, e.g. dropdown menus, into forms? #3

@bbarker

Description

@bbarker

I have a form widget that looks like this, which was taken from the metajelo-ui example and modified slightly:

instContactWidg :: FState -> Widget HTML M.InstitutionContact
instContactWidg fstate = do
  query <- D.div' [
      D.div' [D.text "Email"]
    , D.input
      [ P.value $ F.getInput proxies.email1 fstate.form
        -- This will help us avoid hitting the server on every single key press.
      , (F.asyncSetValidate debounceTime proxies.email1 <<< P.unsafeTargetValue) <$> P.onChange
      ]
    , errorDisplay $ F.getError proxies.email1 fstate.form
    , D.div' [D.text "Confirm Email"]
    , D.input
      [ P.value $ F.getInput proxies.email2 fstate.form
      , (F.asyncSetValidate debounceTime proxies.email2 <<< P.unsafeTargetValue) <$> P.onChange
      ]
    , errorDisplay $ F.getError proxies.email2 fstate.form
    , D.div' [D.text "Contact type"]
    , D.menu
      [ P.value $ F.getInput proxies.contactType fstate.form
      , (F.set proxies.contactType <<< P.unsafeTargetValue) <$> P.onChange
      ]
    -- , D.input
    --   [ P.value $ F.getInput proxies.contactType fstate.form
    --   , (F.set proxies.contactType <<< P.unsafeTargetValue) <$> P.onChange
    --   ]
    , errorDisplay $ F.getError proxies.contactType fstate.form
    , D.div' [F.submit <$ D.button [P.onClick] [D.text "Submit"]]
    ]
  res <- F.eval query fstate
  case res of
    Left fstate' -> instContactWidg fstate'
    Right out -> do
      let form = F.unwrapOutputFields out
      pure {emailAddress: form.email1, contactType: form.contactType}
  where
    errorDisplay = maybe mempty (\err -> D.div [P.style {color: "red"}] [D.text $ V.toText err])
    debounceTime = Milliseconds 300.0

The main issue is that when I want to change the text input field defined by:

    -- , D.input
    --   [ P.value $ F.getInput proxies.contactType fstate.form
    --   , (F.set proxies.contactType <<< P.unsafeTargetValue) <$> P.onChange
    --   ]

to a dropdown menu (nonfunctioning as expected):

    , D.menu
      [ P.value $ F.getInput proxies.contactType fstate.form
      , (F.set proxies.contactType <<< P.unsafeTargetValue) <$> P.onChange
      ]

things like F.getInput no longer make sense here.

It isn't clear to me what the best approach would be in general - try to find some way to get e.g. menus to work within a form, or to just have the form not return the complete data type, and integrate it into some regular Concur code to get the full value (in this case of type InstitutionContact).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions