All Projects → etaque → Elm Form

etaque / Elm Form

Licence: bsd-3-clause
Dynamic forms handling in Elm

Programming Languages

elm
856 projects

Projects that are alternatives of or similar to Elm Form

Form For
ReactJS forms made easy
Stars: ✭ 118 (-37.57%)
Mutual labels:  form-validation, form, form-builder
grav-plugin-form
Grav Form Plugin
Stars: ✭ 48 (-74.6%)
Mutual labels:  form, form-validation, form-builder
antd-react-form-builder
Example
Stars: ✭ 74 (-60.85%)
Mutual labels:  form, form-validation, form-builder
React Hook Form
📋 React Hooks for form state management and validation (Web + React Native)
Stars: ✭ 24,831 (+13038.1%)
Mutual labels:  form-validation, form, form-builder
react-cool-form
😎 📋 React hooks for forms state and validation, less code more performant.
Stars: ✭ 246 (+30.16%)
Mutual labels:  form, form-validation, form-builder
Usetheform
React library for composing declarative forms, manage their state, handling their validation and much more.
Stars: ✭ 40 (-78.84%)
Mutual labels:  form-validation, form, form-builder
React Form With Constraints
Simple form validation for React
Stars: ✭ 117 (-38.1%)
Mutual labels:  form-validation, form
Composable Form
Build type-safe composable forms in Elm
Stars: ✭ 179 (-5.29%)
Mutual labels:  form-validation, form
Formr
Create and Validate PHP Forms in Seconds.
Stars: ✭ 163 (-13.76%)
Mutual labels:  form-validation, form-builder
Sveltejs Forms
Declarative forms for Svelte
Stars: ✭ 163 (-13.76%)
Mutual labels:  form-validation, form
Formsy Semantic Ui React
Formsy-React wrappers for Semantic-Ui-React's form components
Stars: ✭ 103 (-45.5%)
Mutual labels:  form-validation, form
Vue Form Components
Clean & minimal vue form elements and form builder with validation
Stars: ✭ 120 (-36.51%)
Mutual labels:  form-validation, form
Redux Form
A Higher Order Component using react-redux to keep form state in a Redux store
Stars: ✭ 12,597 (+6565.08%)
Mutual labels:  form-validation, form
React Native Form Builder
Handle your forms in a smart way
Stars: ✭ 113 (-40.21%)
Mutual labels:  form, form-builder
Bootstrap Validate
A simple Form Validation Library for Bootstrap 3 and Bootstrap 4 not depending on jQuery.
Stars: ✭ 112 (-40.74%)
Mutual labels:  form-validation, form
Jafar
🌟!(Just another form application renderer)
Stars: ✭ 107 (-43.39%)
Mutual labels:  form-validation, form
React Controlled Form
Flexible, Modular & Controlled Forms for React and Redux
Stars: ✭ 121 (-35.98%)
Mutual labels:  form-validation, form
Formhelper
ASP.NET Core - Transform server-side validations to client-side without writing any javascript code. (Compatible with Fluent Validation)
Stars: ✭ 155 (-17.99%)
Mutual labels:  form-validation, form
Forms
📝 Simple form & survey app for Nextcloud
Stars: ✭ 127 (-32.8%)
Mutual labels:  form, form-builder
Core
The Form Tools Core.
Stars: ✭ 156 (-17.46%)
Mutual labels:  form, form-builder

Elm Form

HTML live form builders and validation for Elm. Build Status

elm package install etaque/elm-form

For when the classical "a message per field" doesn't work well for you, at the price of losing some type safety (field names are made of strings, see #97).

Support

We have a dedicated channel in Elm slack, join us in #elm-form for any question, support or issues coordination.

Features

  • Validation API similar to Json.Decode with the standard map, andThen, etc: you either get the desired output value or all field errors
  • HTML inputs helpers with pre-wired handlers for live validation
  • Suite of basic validations, with a way to add your own
  • Unlimited fields, see andMap function (as in Json.Extra)
  • Nested fields (foo.bar.baz) and lists (todos.1.checked) enabling rich form build

See complete example here (source code).

Basic usage

See the example validation test suite and test helper function docs for how to test-drive validations.

module Main exposing (Foo, Model, Msg(..), app, formView, init, update, validate, view)

import Browser
import Form exposing (Form)
import Form.Input as Input
import Form.Validate as Validate exposing (..)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)



-- your expected form output


type alias Foo =
    { bar : String
    , baz : Bool
    }



-- Add form to your model and msgs


type alias Model =
    { form : Form () Foo }


type Msg
    = NoOp
    | FormMsg Form.Msg



-- Setup form validation


init : Model
init =
    { form = Form.initial [] validate }


validate : Validation () Foo
validate =
    succeed Foo
        |> andMap (field "bar" email)
        |> andMap (field "baz" bool)



-- Forward form msgs to Form.update


update : Msg -> Model -> Model
update msg ({ form } as model) =
    case msg of
        NoOp ->
            model

        FormMsg formMsg ->
            { model | form = Form.update validate formMsg form }



-- Render form with Input helpers


view : Model -> Html Msg
view { form } =
    Html.map FormMsg (formView form)


formView : Form () Foo -> Html Form.Msg
formView form =
    let
        -- error presenter
        errorFor field =
            case field.liveError of
                Just error ->
                    -- replace toString with your own translations
                    div [ class "error" ] [ text (Debug.toString error) ]

                Nothing ->
                    text ""

        -- fields states
        bar =
            Form.getFieldAsString "bar" form

        baz =
            Form.getFieldAsBool "baz" form
    in
    div []
        [ label [] [ text "Bar" ]
        , Input.textInput bar []
        , errorFor bar
        , label []
            [ Input.checkboxInput baz []
            , text "Baz"
            ]
        , errorFor baz
        , button
            [ onClick Form.Submit ]
            [ text "Submit" ]
        ]


app =
    Browser.sandbox
        { init = init
        , update = update
        , view = view
        }

Advanced usage

Custom inputs

  • For rendering, Form.getFieldAsString/Bool provides a FieldState record with all required fields (see package doc).

  • For event handling, see all field related messages in Form.Msg type.

Overall, having a look at current helpers source code should give you a good idea of the thing.

Incremental validation

Similar to what Json.Extra provides you can also use Form.andMap

Form.succeed Player
    |> andMap (field "email" (string |> andThen email))
    |> andMap (field "power" int)

Nested records

  • Validation:
validation =
    map2 Player
        (field "email" (string |> andThen email))
        (field "power" (int |> andThen (minInt 0)))
        (field "options"
            (map2 Options
                (field "foo" string)
                (field "bar" string)
            )
        )
  • View:
Input.textInput (Form.getFieldAsString "options.foo" form) []

Dynamic lists

-- model
type alias TodoList =
    { title : String
    , items : List String
    }

-- validation
validation : Validation () Issue
validation =
    map2 TodoList
        (field "title" string)
        (field "items" (list string))

-- view
formView : Form () Issue -> Html Form.Msg
formView form =
    div
        [ class "todo-list" ]
        [ Input.textInput
            (Form.getFieldAsString "title" form)
            [ placeholder "Title" ]
        , div [ class "items" ] <|
            List.map
                (itemView form)
                (Form.getListIndexes "items" form)
        , button
            [ class "add"
            , onClick (Form.Append "items")
            ]
            [ text "Add" ]
        ]

itemView : Form () Issue -> Int -> Html Form.Msg
itemView form i =
    div
        [ class "item" ]
        [ Input.textInput
            (Form.getFieldAsString ("items." ++ (String.fromInt i)) form)
            []
        , a
            [ class "remove"
            , onClick (Form.RemoveItem "items" i)
            ]
            [ text "Remove" ]
        ]

Initial values and reset

  • At form initialization:
import Form.Field as Field


initialFields : List ( String, Field )
initialFields =
    [ ( "power", Field.string "10" )
    , ( "options"
      , Field.group
            [ ( "foo", Field.string "blah" )
            , ( "bar", Field.string "meh" )
            ]
      )
    ]


initialForm : Form
initialForm =
    Form.initial initialFields validation

See Form.Field type for more options.

  • On demand:
button [ onClick (Form.Reset initialFields) ] [ text "Reset" ]

Note: To have programmatic control over any input[type=text]/textarea value, like reseting or changing the value, you must set the value attribute with Maybe.withDefault "" state.value, as seen here. There's a downside of doing this: if the user types too fast, the caret can go crazy.

More info: https://github.com/evancz/elm-html/pull/81#issuecomment-145676200

Custom errors

type LocalError = Fatal | NotSoBad

validation : Validation LocalError Foo
validation =
    (field "foo" (string |> customError Fatal))

-- creates `Form.Error.CustomError Fatal`

Async validation

This package doesn't provide anything special for async validation, but doesn't prevent you to do that either. As field values are accessible from update with Form.getStringAt/getBoolAt, you can process them as you need, trigger effects like an HTTP request, and then add any errors to the view by yourself.

Another way would be to enable dynamic validation reload, to make it dependant of an effect, as it's part of the form state. Please ping me if this feature would be useful to you.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].