hecrj/composable-form/2.1.0

NOTE: this package is not compatible with Elm 0.19.1

Form.View

This module provides helpers to render a Form.

If you just want to quickly render a Form as HTML, take a look at asHtml. If you need more control, use custom.

Note: If you are implementing your own custom fields using Form.Base then you cannot use this module. You should use Form.Base.fill to write your own renderer. Take a look at the source code of this module for inspiration.

Model

type alias Model values =
{ values : values
, state : State
, errorTracking : ErrorTracking
}

This type gathers the values of the form, with some exposed state and internal view state that tracks which fields should show validation errors.

type State
= Idle
| Loading
| Error String

Represents the state of the form.

You can change it at will from your update function. For example, you can set the state to Loading if submitting the form fires a remote action, or you can set it to Error when such action fails.

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        FormChanged newModel ->
            ( { newModel | state = FormView.Idle }, Cmd.none )


        SignUp email password ->
            ( { model | state = FormView.Loading }
            , User.signUp email password
                |> Task.attempt SignupTried
            )


        SignupTried (Ok user) ->
            ( model, Route.navigate (Route.Profile user.slug) )


        SignupTried (Err error) ->
            ( { model | state = FormView.Error error }, Cmd.none )
idle : values -> Model values

Create a Model representing an idle form.

You just need to provide the initial values of the form.

Configuration

type alias ViewConfig values msg =
{ onChange : Model values -> msg
, action : String
, loading : String
, validation : Validation
}

This allows you to configure the renderer behavior.

  • onChange specifies the message that should be produced when the Model changes.
  • action is the text of the submit button when the form is not loading.
  • loading is the text of the submit button when the form is loading.
  • validation lets you choose the validation strategy.
= ValidateOnSubmit
| ValidateOnBlur

The validation strategy.

  • ValidateOnSubmit will show field errors only when the user tries to submit an invalid form.
  • ValidateOnBlur will show field errors as fields are blurred.

Built-in HTML renderer

asHtml : ViewConfig values msg -> Form values msg -> Model values -> Html msg

Render a form as HTML!

You could use it like this:

FormView.asHtml
    { onChange = FormChanged
    , action = "Log in"
    , loading = "Logging in..."
    , validation = FormView.ValidateOnSubmit
    }
    loginForm
    model

And here is an example of the produced HTML:

<form class="elm-form">
   <div class="elm-form-field">
       <label>E-Mail</label>
       <input type="email" value="[email protected]" placeholder="Type your e-mail...">
   </div>
   <div class="elm-form-field elm-form-field-error">
       <label>Password</label>
       <input type="password" value="" placeholder="Type your password...">
       <div class="elm-form-error">This field is required</div>
   </div>
   <button type="submit">Log in</button>
</form>

You can use the different CSS classes to style your forms as you please.

If you need more control over the produced HTML, use custom.

Custom renderer

CustomConfig msg element
-> ViewConfig values msg
-> Form values msg
-> Model values
-> element

Create a custom renderer.

You need to provide a set of functions to render each field, and a function to put them all together in a form, see CustomConfig.

This function can be used to create form renderers that are compatible with style-elements, elm-mdl, elm-css, etc. You could even use it to transform forms into a String or Json.Value!

Once you provide a CustomConfig this function returns a renderer that supports a ViewConfig. In fact, asHtml is implemented using this function!

asHtml : ViewConfig values msg -> Form values msg -> Model values -> Html msg
asHtml =
    custom
        { form = form
        , textField = inputField "text"
        , emailField = inputField "email"
        , passwordField = inputField "password"
        , searchField = inputField "search"
        , textareaField = textareaField
        , numberField = numberField
        , rangeField = rangeField
        , checkboxField = checkboxField
        , radioField = radioField
        , selectField = selectField
        , group = group
        }
type alias CustomConfig msg element =
{ form : FormConfig msg element -> element
, textField : TextFieldConfig msg -> element
, emailField : TextFieldConfig msg -> element
, passwordField : TextFieldConfig msg -> element
, textareaField : TextFieldConfig msg -> element
, searchField : TextFieldConfig msg -> element
, numberField : NumberFieldConfig msg -> element
, rangeField : RangeFieldConfig msg -> element
, checkboxField : CheckboxFieldConfig msg -> element
, radioField : RadioFieldConfig msg -> element
, selectField : SelectFieldConfig msg -> element
, group : List element -> element
}

The configuration needed to create a custom renderer.

It needs functions to render each of the supported Form fields, a function to render a group of fields, and a function to wrap the fields together in a form.

type alias FormConfig msg element =
{ onSubmit : Maybe msg
, state : State
, action : String
, loading : String
, fields : List element
}

Describes how a form should be rendered.

  • onSubmit contains the output of the form if there are no validation errors.
  • state is the State of the form.
  • action is the main action of the form, you should probably render this in the submit button.
  • loading is the loading message that should be shown when the form is loading.
  • fields contains the already rendered fields.
type alias TextFieldConfig msg =
{ onChange : String -> msg
, onBlur : Maybe msg
, disabled : Bool
, value : String
, error : Maybe Error
, showError : Bool
, attributes : Attributes
}

Describes how a text field should be rendered.

  • onChange takes a new value for the field and returns the msg that should be produced.
  • onBlur might contain a msg that should be produced when the field is blurred.
  • disabled tells you whether the field should be disabled or not. It is True when the form is loading.
  • value contains the current value of the field.
  • error might contain a field Error.
  • showError tells you if you should show the error for this particular field. Its value depends on the validation strategy.
  • attributes are TextField.Attributes.
type alias NumberFieldConfig msg =
{ onChange : Float -> msg
, onBlur : Maybe msg
, disabled : Bool
, value : Maybe Float
, error : Maybe Error
, showError : Bool
, attributes : Attributes
}

Describes how a number field should be rendered.

The other record fields are described in TextFieldConfig.

type alias RangeFieldConfig msg =
{ onChange : Float -> msg
, onBlur : Maybe msg
, disabled : Bool
, value : Maybe Float
, error : Maybe Error
, showError : Bool
, attributes : Attributes
}

Describes how a range field should be rendered.

The other record fields are described in TextFieldConfig.

type alias CheckboxFieldConfig msg =
{ onChange : Bool -> msg
, onBlur : Maybe msg
, disabled : Bool
, value : Bool
, error : Maybe Error
, showError : Bool
, attributes : Attributes
}

Describes how a checkbox field should be rendered.

This is basically a TextFieldConfig, but its attributes are CheckboxField.Attributes.

type alias RadioFieldConfig msg =
{ onChange : String -> msg
, onBlur : Maybe msg
, disabled : Bool
, value : String
, error : Maybe Error
, showError : Bool
, attributes : Attributes
}

Describes how a radio field should be rendered.

This is basically a TextFieldConfig, but its attributes are RadioField.Attributes.

type alias SelectFieldConfig msg =
{ onChange : String -> msg
, onBlur : Maybe msg
, disabled : Bool
, value : String
, error : Maybe Error
, showError : Bool
, attributes : Attributes
}

Describes how a select field should be rendered.

This is basically a TextFieldConfig, but its attributes are SelectField.Attributes.