Announcing elm-field
Dwayne Crooks

Dwayne Crooks @dwayne

About: Learn to build reliable web applications with Elm.

Location:
Trinidad & Tobago
Joined:
Apr 29, 2019

Announcing elm-field

Publish Date: Aug 18
6 0

I'm happy to announce the release of dwayne/elm-field.

dwayne/elm-field is an Elm package for constructing valid data from unreliable string inputs. It provides a Field data structure that models the non-UI related aspects of an input field. I extracted this package from my work on L-System Studio.

Think about a Field in a similar way as you'd think about Maybe, Result, and Validation. Suppose you're parsing a String into a value of some type, say a. There's the potential for one or more errors to occur. If you just want to know that an error occurred but you don't care about the specific error that occurred you'd use Maybe. If you do care to track the specific errors then you'd switch to Result. Furthermore, if you care to accumulate multiple specific errors you'd change to a Validation.

A Field is like a Validation in that it allows you to accumulate multiple specific errors. But, it also does a little bit more.

  1. It remembers the original raw String you were trying to parse.
  2. It remembers whether or not it's the first time you're changing the String to be parsed, i.e. whether or not your field is clean or dirty.
  3. It keeps track of the function used to parse the String. And,
  4. It keeps track of the function used to convert the value back to a String.

The last two constitute the Type of a Field.

The package provides two modules: Field and Field.Advanced. The difference between them is that Field.Advanced allows you to use a custom type to track your errors whereas Field uses strings for errors.

An example

Suppose you need to accept input from a user for a positive integer, i.e. an integer greater than or equal to 1. Here's what that might look like:

import Field as F exposing (Field)
...

type alias Model =
    { n : Field Int
    , ...
    }

init : Model
init =
    { n = F.empty F.positiveInt
    , ...
    }

type Msg
    = Input String
    | ...

update : Msg -> Model -> Model
update msg model =
    case msg of
        Input s ->
            { model | n = F.setFromString s model.n }

        ...

view : Model -> H.Html Msg
view model =
    ...
    H.input
        [ HA.type_ "text"
        , HA.value (F.toRawString model.n)
        , ...
        , HE.onInput Input
        ]
        []
    ...
Enter fullscreen mode Exit fullscreen mode

In general, you can easily create a field out of any of Elm's primitive types: Int, Float, Bool, Char, and String.

For many more examples you can read the README, play with the demos, and examine the unit tests.

No UI

I want to stress that a Field data structure models the non-UI related aspects of an input field. This means you can implement the business logic for a form and reuse that logic to render your form in infinitely many ways. Take the sign up form example. The simple view and the complex view are different renderings of the same underlying form. You have complete control over the UI.

Richard's comment

If you resonate with Richard's comment then my package attempts to provide a better tool for working with forms as programs. Give it a try and let me know what you think.

Subscribe to my newsletter

If you're interested in improving your skills with Elm then I invite you to subscribe to my newsletter, Elm with Dwayne. To learn more about it, please read this announcement.

Comments 0 total

    Add comment