axelerator / fancy-forms / FancyForms.Form

FancyForms is a library for building forms in Elm. It is designed with the following goals in mind:

  1. Type saftey: Data collected in the forms will be returned directly into a user provided type.
  2. Ease of use: No matter how complex the form is, it will only need one Msg and one field on the model.
  3. Customization: Users can provide their own widgets and custom validations.
  4. CSS Agnostic: Adapts to any CSS framework.
  5. Composable: Smaller forms can be combined into larger forms.
  6. I18n: Internationalization is supported by avoiding hard coded strings.

Definition


type alias Form data customError =
PartialForm { view : FancyForms.FormState.FormState -> List (FancyForms.FormState.Error customError) -> List (Html Msg)
, combine : FancyForms.FormState.FormState -> data } customError dat
}

A form that collects a value of type data and potentially produces errors of type customError.

form : FieldWithErrors customError -> FancyForms.FormState.Validator data customError -> FancyForms.FormState.DomId -> a -> PartialForm a customError data

Defines a new form that fields can be added to. Takes four arguments: 1, A unique id for the form to be used as id in the DOM

  1. A validator function that takes the form data and returns a list of errors

  2. A function that receives the fields and returns the view and combine functions

  3. A function that receives the markup of a field and combines it with a list of errors

    myForm : Form Int ()
    myForm =
        Form.form
            (\errors_ html -> html)
            (\data -> [])
            "minimal-example"
            (\amount ->
                { view = \formState _ -> amount.view formState
                , combine = \formState -> amount.value formState
                }
            )
            |> field (integerInput [])
    

field : (data -> value) -> FancyForms.FormState.Widget widgetModel msg value customError -> PartialForm (Field value customError -> c) customError data -> PartialForm c customError data

Adds a new field with the given widget to the form


type alias Field a customError =
{ id : FancyForms.FormState.FieldId
, value : FancyForms.FormState.FormState -> a
, errors : FancyForms.FormState.FormState -> List (FancyForms.FormState.Error customError)
, view : FancyForms.FormState.FormState -> List (Html Msg)
, multiple : Basics.Bool 
}

The type of a field in the form.

isValid : Form data customError -> FancyForms.FormState.FormState -> Basics.Bool

Returns true if the data entered in the form is valid

validate : List (FancyForms.FormState.Validator value customError) -> FancyForms.FormState.Widget model msg value customError -> FancyForms.FormState.Widget model msg value customError

Adds a validator to a widget.


type alias FieldWithErrors customError =
List (FancyForms.FormState.Error customError) -> List (Html Msg) -> List (Html Msg)

A function that recieves the markup of a field and combines with a list of errors.


type alias PartialForm f customError data =
{ fn : f
, count : Basics.Int
, updates : Dict FancyForms.FormState.FieldId (FancyForms.FormState.SubfieldId -> FancyForms.FormState.FieldOperation -> Json.Encode.Value -> ( Json.Encode.Value
, FancyForms.FormState.Effect ))
, fieldWithErrors : FieldWithErrors customError
, validator : FancyForms.FormState.Validator data customError
, blur : FancyForms.FormState.FormState -> FancyForms.FormState.FormState
, domId : FancyForms.FormState.DomId
, isConsistent : FancyForms.FormState.FormState -> Basics.Bool
, initWithData : data -> FancyForms.FormState.FormState -> FancyForms.FormState.FormState 
}

Represents a form that still needs it's fields to be declared. Once all the fields that the view function consumes are declared it is not "partial" anymore.

Wiring


type Msg

The message type for the form.

init : Form data customError -> data -> FancyForms.FormState.FormState

Initializes a form state with the default values

update : Form a customError -> Msg -> FancyForms.FormState.FormState -> FancyForms.FormState.FormState

Updates the form state based on the form message.

render : (Msg -> msg) -> Form a customError -> FancyForms.FormState.FormState -> List (Html msg)

Takes the following three arguments to display a form:

  1. a function to turn the forms messages into a Msg of the application.

  2. the form

  3. the current state of the form

    type Msg = ... | ForForm Form.Msg | ... type alias Model = { ... , formState : FormState, .. } myForm = Form.form ...

    view model = div [] <| Form.render ForForm myForm model.formState

extract : Form data customError -> FancyForms.FormState.FormState -> data

Returns the result of the combine function aka the current state of the form.

List fields

listField : ListWithAddButton Msg -> FieldWithRemoveButton Msg -> value -> (data -> List value) -> FancyForms.FormState.Widget model msg value customError -> { a | fn : Field (List value) customError -> b, count : Basics.Int, updates : Dict String (FancyForms.FormState.SubfieldId -> FancyForms.FormState.FieldOperation -> Json.Encode.Value -> ( Json.Encode.Value, FancyForms.FormState.Effect )), fieldWithErrors : FieldWithErrors customError, validator : e, blur : c -> FancyForms.FormState.FormState, domId : FancyForms.FormState.DomId, isConsistent : FancyForms.FormState.FormState -> Basics.Bool, initWithData : data -> FancyForms.FormState.FormState -> FancyForms.FormState.FormState } -> { fn : b, count : Basics.Int, updates : Dict String (FancyForms.FormState.SubfieldId -> FancyForms.FormState.FieldOperation -> Json.Encode.Value -> ( Json.Encode.Value, FancyForms.FormState.Effect )), fieldWithErrors : FieldWithErrors customError, validator : e, blur : c -> FancyForms.FormState.FormState, domId : FancyForms.FormState.DomId, isConsistent : FancyForms.FormState.FormState -> Basics.Bool, initWithData : data -> FancyForms.FormState.FormState -> FancyForms.FormState.FormState }

Adds a field to the form where the user can add and remove elements.

The first argument is a ListWithAddButton function that cobines the inout list with a button to add a new element.

The second argument is a FieldWithRemoveButton function that combines one item with a button to remove it.

The third argument is the widget to use for each element in the list.


type alias FieldWithRemoveButton msg =
msg -> List (Html msg) -> List (Html msg)

A function that recieves the markup of a list item and combines it with a butoon to remive it from the List.


type alias ListWithAddButton msg =
msg -> List (Html msg) -> List (Html msg)

A function that recieves the markup of a field and combines it with a button to add a new item.

Fields with Variants

fieldWithVariants : (data -> value) -> (Variants String -> FancyForms.FormState.Widget String msg String customError) -> ( String, Form value customError ) -> List ( String, Form value customError ) -> (value -> String) -> PartialForm (Field value customError -> c) customError data -> PartialForm c customError data

Adds a new field to with different variants to the form. Each variant is represented by a label and a sub form.

The function takes the following arguments:

  1. A widget to select the variant
  2. The default variant
  3. A list of other variants


type alias Variant a =
{ value : a
, id : String
, label : String 
}

A variant for widgets with a "select" notion.


type alias Variants a =
List.Nonempty.ListNonempty (Variant a)

A nonempty list of variants.

Composition

toWidget : Form a customError -> FancyForms.FormState.Widget FancyForms.FormState.FormState Msg a customError

Converts a form to a widget.

wrap : FancyForms.FormState.Widget widgetModel msg value customError -> (FancyForms.FormState.DomId -> List (Html msg) -> List (Html msg)) -> FancyForms.FormState.Widget widgetModel msg value customError

Creates a new Widget that's decorated with the given function.