cekrem/elm-form/1.1.1

Input

Build type-safe HTML input elements with validation and state management.

This module uses phantom types to ensure inputs are properly configured before being rendered. An input must have interaction (via withOnChange or withDisabled) before it can be built into HTML.

Types

type Input interaction msg

An input element with a phantom type parameter for compile-time state tracking.

The phantom type ensures that inputs have proper interaction handlers before they can be rendered.

type Dumb

Phantom type representing an input without interaction.

Inputs with this type cannot be built yet - they need to be given interaction via withOnChange or withDisabled.

Phantom type representing an input with interaction.

Inputs with this type can be built into HTML.

Creating Inputs

new : String -> Input Dumb msg

Create a new input with a label.

The input starts as Dumb, meaning it cannot be built yet. You must add interaction via withOnChange or withDisabled before building.

new "Email Address"


new "Password"
    |> withType "password"
    |> withRequired True
    |> withOnChange PasswordChanged

Configuration

withRequired : Bool -> Input any msg -> Input any msg

Mark an input as required or optional.

This sets the HTML required attribute.

new "Email"
    |> withRequired True
withType : String -> Input any msg -> Input any msg

Set the input type (e.g., "text", "email", "password", "number").

new "Password"
    |> withType "password"
    |> withRequired True
    |> withOnChange PasswordChanged
withPlaceholder : String -> Input any msg -> Input any msg

Add placeholder text to an input.

new "Search"
    |> withPlaceholder "Type to search..."
    |> withOnChange SearchChanged
withTransformer : (String -> String) -> Input any msg -> Input any msg

Add a transformer function that processes the input value.

The transformer is applied to the value before it's passed to the onChange handler. This is useful for formatting, trimming, or normalizing input.

new "Username"
    |> withTransformer String.trim
    |> withOnChange UsernameChanged


new "Code"
    |> withTransformer String.toUpper
    |> withOnChange CodeChanged
(String -> Result (List (Attribute msg)) ())
-> Input any msg
-> Input any msg

Add a validator function that returns additional HTML attributes on validation failure.

The validator receives the current value and can return error attributes that will be applied to the input element. This is useful for providing visual feedback or ARIA attributes for accessibility.

import Html.Attributes as Attr


lengthValidator : String -> Result (List (Html.Attribute msg)) ()
lengthValidator value =
    if String.length value >= 3 then
        Ok ()
    else
        Err
            [ Attr.class "invalid"
            , Attr.attribute "aria-invalid" "true"
            ]


new "Username"
    |> withValidator lengthValidator
    |> withOnChange UsernameChanged
withAttributes : List (Attribute msg) -> Input any msg -> Input any msg

Add custom HTML attributes to an input.

import Html.Attributes as Attr


new "Email"
    |> withAttributes
        [ Attr.class "form-input"
        , Attr.autocomplete False
        ]
    |> withOnChange EmailChanged

Adding Interaction

withOnChange : (String -> msg) -> Input Dumb msg -> Input WithInteraction msg

Add an onChange handler to make the input interactive.

This is required before an input can be built. The handler receives the transformed value after any transformer has been applied.

type Msg
    = NameChanged String


new "Name"
    |> withTransformer String.trim
    |> withOnChange NameChanged
    |> build currentValue

Convert a Dumb input to a disabled input with interaction.

This allows you to build a disabled input without providing an onChange handler.

new "Disabled Field"
    |> withDisabled
    |> build ""

Rendering

build : String -> Input WithInteraction msg -> Html msg

Build an input into HTML.

The input must have interaction (via withOnChange or withDisabled) to be buildable. The build function is optimized with lazy rendering for performance.

type Msg
    = EmailChanged String


view : String -> Html Msg
view emailValue =
    new "Email"
        |> withType "email"
        |> withRequired True
        |> withOnChange EmailChanged
        |> build emailValue