/nativeform

Working with form in Elm without storing raw form state in Elm. Demo at https://nativeform.netlify.app

Primary LanguageElmMIT LicenseMIT

NativeForm

Working with form in Elm without storing raw form state in Elm, aka "Use the Platform".

Before

  1. Use value someValue to set form field value when we render a form (e.g. edit form)
    • we are now obliged to keep someValue in sync with user's input
  2. Use onInput msg to update someValue
    • store this value in model
    • this value may not be the desired type, e.g. storing raw String on behalf of a Time.Posix model state

After

  1. Use defaultValue someValue to set form field value when we render a form (e.g. edit form)
    • no longer obliged to keep someValue in sync with user's input
  2. Use NativeForm.decoder anytime to retrieve the form values from browser document.forms
    • No need for onInput nor a msg for every form field; only do so for fields that really need handling
    • But forms must be given the id attribute and form fields must be given a name attribute

Demo

Checkout the demo at https://nativeform.netlify.app and its source code at example subdirectory.

Getting started

  1. Pass the browser document.forms into your Elm app through Flags

    <script>
    var app = Elm.Main.init({
        node: document.getElementById('myapp'),
        flags: {
            documentForms: document.forms // <-- important!
        }
    })
    </script>
  2. Store the documentForms : Json.Encode.Value from your Flags in your Model

  3. Wire up any (or many) events, e.g. form [ on "change" OnFormChange ] or input [ onInput (always OnFormChange) ]

  4. And call Json.Decode.decodeValue (NativeForm.decoder formId) model.documentForms to get the list of form field name and values.

Notes

  1. No matter how many fields you have, you only need one Msg

  2. Always give your form an id value

  3. Always give your form fields a name value

  4. Does not handle input[type=file] in a useful manner; manage file uploads by other means.

  5. All user input values are either OneValue String or ManyValues (List String), including input[type=number]; do your own conversion to Int or Time.Posix etc.

  6. When using this library, your form id and field names are "stringly typed". You should use a custom type to manage a fixed set of form fields, but this library does not require you to do so.

  7. Do not deal with the List (String, Value) returned from NativeForm.decoder. Instead, you should parse them into a value of your desired type. e.g.

    parseDontValidate :
        List ( String, NativeForm.Value )
        -> Result String UserInfo
    

    See a sample parseDontValidate implementation