hecrj/composable-form/4.0.0

NOTE: the latest version is 8.0.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 custom view code. 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 view output.

  • 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.

Basic HTML

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

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

Create a custom view function.

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 can be used to create view functions 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! Take a look at the different view modules in the examples directory as you might find an implementation that works for you.

Once you provide a CustomConfig, you get a view function 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 view function.

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 : Maybe Float -> msg
, onBlur : Maybe msg
, disabled : Bool
, value : Maybe Float
, error : Maybe Error
, showError : Bool
, attributes : Attributes Float
}

Describes how a number field should be rendered.

  • onChange accepts a Maybe so the field value can be cleared.
  • value will be Nothing if the field is blank or Just a Float.
  • attributes are NumberField.Attributes.

The other record fields are described in TextFieldConfig.

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

Describes how a range field should be rendered.

  • onChange accepts a Maybe so the field value can be cleared.
  • value will be Nothing if the field is blank or Just a Float.
  • attributes are RangeField.Attributes.

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.