The base for a text field. You can add display modifiers to text fields, including displaying them as a textarea.
See Text Field Display Options.
By default, text fields are not required. If the field is not touched or has been deleted, the value will be Nothing
(not empty string Just ""). See required.
import Form.Field as Field
type alias Profile =
{ status : Maybe String
}
example =
(\username ->
{ combine =
Validation.succeed Status
|> Validation.andMap username
, view = []
}
)
|> Form.form
|> Form.field "status" Field.textRenders a checkbox input (<input type="checkbox" />), see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox.
import Form.Field as Field
example =
Field.checkboxRenders a number input (<input type="number" />), see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/number.
Floating point numbers will give a validation error, using the error value passed in through the invalid function.
import Form.Field as Field
example =
Field.number
{ invalid =
\value -> "Must be an integer"
}A number input (<input type="number" />), see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/number.
Unlike int, this field allows floating point numbers.
It will give a validation error if the input is not a number, using the error value passed in through the invalid function.
import Form.Field as Field
example =
Field.number
{ invalid =
\value -> "Must be a number"
}An input for a set of possible options. Can be rendered in two ways
<select>)Form.FieldView.select<input type="radio" />)Form.FieldView.radio.import Form
import Form.Field as Field
import Form.FieldView as FieldView
import Form.Validation as Validation
sizeForm : Form.HtmlForm String Size input msg
sizeForm =
(\size ->
{ combine =
Validation.succeed identity
|> Validation.andMap size
, view =
\formState ->
[ Html.div []
[ FieldView.select []
(\entry -> ( [], sizeToString entry ))
size
]
, Html.button [] [ Html.text "Submit" ]
]
}
)
|> Form.form
|> Form.field "size"
(Field.select
[ ( "small", Small )
, ( "medium", Medium )
, ( "large", Large )
]
(\_ -> "Invalid")
|> Field.required "Required"
|> Field.withInitialValue (\_ -> Small)
)
sizeToString : Size -> String
sizeToString size =
case size of
Small ->
"Small"
Medium ->
"Medium"
Large ->
"Large"
type Size
= Small
| Medium
| LargeUsed for errors from a range Field.
A date field. Parses into a value of type Date.
example =
Field.date
{ invalid = \_ -> "Invalid date" }
|> Field.required "Required"
|> Field.withMin (Date.fromRataDie 738624) "Must be after today"
-- date picker will show dates on the same day of the week starting from the start date
|> Field.withStep 7A time of day in 24-hour time.
The hours must be between 0 and 23, and the minutes must be between 0 and 59.
This is the type that a time field parses into, and is also used to set initial values and minimum/maximum values for time.
See https://developer.mozilla.org/en-US/docs/Web/HTML/Date_and_time_formats#time_strings
Set an initial value for the Field given the Form's input (see Form.withInput).
This allows you to pass in dynamic state like values from your Model.
The initial value will be used until the field is modified by the user, and from there it is controlled by user input. If you
need to programmatically set a field's value for more advanced use cases, you can also modify the Form.Model.
The type you use to set the initial value depends on the Field. For example, you can set a checkbox Field's initial value
with a Bool
example =
Form.checkbox |> Form.withInitialValue .autoplay
formOptions : { autoplay : Bool } -> Form.Options String parsed { autoplay : Bool } msg
formOptions currentSettings =
Form.options "settings"
|> Form.withInput currentSettingsNote that the type used to set the initial value is independent of types you might map a field into.
Similar to withInitialValue, but takes in a Maybe value. If the Maybe is Nothing then it's
the same as if no initial value were set.
example =
Form.text |> Form.withOptionalInitialValue .nickname
formOptions : { nickname : Maybe String } -> Form.Options String parsed { nickname : Maybe String } msg
formOptions currentProfile =
Form.options "profile"
|> Form.withInput currentProfileRender a field with a hardcoded value.
Gives a validation error for fields that haven't been set, and removes the Maybe around the parsed value.
example =
Field.int { invalid = \_ -> "Invalid" }
-- parses into `Maybe Int` before we call `required`
-- after `required`, it parses into an `Int`
|> Field.required "Required"Add a custom validation and/or transformation of the value to the field.
import Form.Field as Field
example =
Field.text
|> Field.required "Required"
|> Field.validateMap Username.fromString
-- in Username.elm
fromString : String -> Result String Username
fromString string =
if string |> String.contains "@" then
Err "Must not contain @"
else
Username string |> OkMap the parsed value of a Field without adding or modifying its validations or rendering.
import Form.Field as Field
example =
Field.text
|> Field.required "Required"
|> Field.map String.toUpperModifier for text Field. This does not perform any additional validations on the Field, it only provides a hint to the browser
that the Field should be displayed as an email input (<input type="email" />). This is especially useful for mobile devices to make sure
the correct keyboard is displayed.
See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/email.
example =
Field.text
|> Field.email
|> Field.required "Email is required"Modifier for text Field. This is only a display hint to the browser that the Field should be displayed as a password input (<input type="password" />).
See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/password.
example =
Field.text
|> Field.password
|> Field.required "Password is required"Modifier for text Field. This changes the display of the Field to a password input (<input type="search" />).
On mobile devices, this will display a keyboard with a search button.
See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/search.
example =
Field.text
|> Field.searchModifier for text Field. This is only a display hint to the browser (<input type="tel" />).
This is especially important on mobile devices for ensuring that the correct keyboard is displayed for inputting a phone number.
See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/tel.
example =
Field.text
|> Field.telephoneModifier for text Field. This does not perform any additional validations on the Field, it only provides a hint to the browser
that the Field should be displayed as a URL input (<input type="url" />).
See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/url.
example =
Field.text
|> Field.url
|> Field.required "URL is required"Modifier for text Field to display it as a textarea.
textarea are for multi-line text input. For example, you might use a regular text Field for a username, and a textarea Field for a biography.
import Form.Field as Field
type alias Profile =
{ username : String
, bio : String
}
example =
(\username bio ->
{ combine =
Validation.succeed Profile
|> Validation.andMap username
|> Validation.andMap bio
, view = []
}
)
|> Form.form
|> Form.field "username"
(Field.text
|> Field.required "Required"
)
|> Form.field "bio"
(Field.text
|> Field.textarea
{ rows = Just 20
, cols = Just 50
}
|> Field.required "Required"
)Display a range input (<input type="range" />). See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/range.
import Form.Field as Field
type alias Settings =
{ brightness : Int
}
example =
(\brightness ->
{ combine =
Validation.succeed Settings
|> Validation.andMap brightness
, view = []
}
)
|> Form.form
|> Form.field "brightness"
(Field.range
{ min = 0
, max = 100
, missing = "Required"
, invalid =
\outsideRange ->
case outsideRange of
Field.AboveRange ->
"Must be below 100"
Field.BelowRange ->
"Must be above 0"
}
(Field.int { invalid = \_ -> "Invalid" })
)Set the min value for the Field. This results in both a validation (run on the server as well as the client) as well as a display hint to the browser
(<input type="date" min="2023-04-14" />). The Browser will prevent the user from entering a value below the min value in some cases but not all.
See https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/min.
If the value is invalid (below the minimum), the error will be whichever error is passed in as the second argument.
import Date exposing (Date)
import Form.Field as Field
example =
Field.date
{ invalid = \_ -> "Must be valid date" }
|> Field.required "Required"
|> Field.withMin today ("Must be after " ++ Date.toIsoString today)
today : Date
today =
Date.fromRataDie 738624Same as withMin but for a maximum value. See https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/max.
import Date exposing (Date)
import Form.Field as Field
example =
Field.date
{ invalid = \_ -> "Must be valid date" }
|> Field.required "Required"
|> Field.withMax today "Cannot schedule more than 7 days in advance"
inAWeek : Date
inAWeek =
Date.fromRataDie (today + 7)
today : Int
today =
738624Set a minimum length for the string. See https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/minlength.
Set a maximum length for the string. See https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/maxlength.
Sets the step attribute on the form field for Field's with Int steps. See https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/step.
For int fields, the step will change the up/down buttons in the field's UI to increment/decrement by the given step.
Int step values have different meanings for different kinds of Fields.
Used in the constraints for a Field. These can't be built or used outside of the API, they are only used as guardrails
to ensure sure that Fields are configured correctly.
Used in the constraints for a Field. These can't be built or used outside of the API, they are only used as guardrails to ensure sure that Fields are configured correctly.
A
Fieldrepresents the base information of how to turn a raw input into a parsed value, and how to display that value as an HTML form field element. Note that you can also perform more advanced validations and mapping using theForm.ValidationAPI in yourcombinefunction.For example, if you want to display a check-in and check-out date field, you would use
dateFields. Usingdatedoes two things:Sets display options for the browser to display the field with
<input type="date" />.Parses into an Elm value of type
Date(or a validation error if the format isn't invalid).Why would the date format be invalid if it is managed by the Browser's date picker element? In the happy path on the Browser this will never happen.
However, you can't make any assumptions about the client (non-standard clients could be used), or about the data format that is sent to servers. Often validation logic is duplicated to guard against this on both the client (display useful validation feedback for the user) and the server (validate untrusted input). If you use full-stack Elm, you can use your Form definition on your server to run the same code that you use to present validation errors on the client, allowing you to keep the validations in sync.
Here is an example that showcases different types of Fields (
text,date,time, andcheckbox), as well as how to use thecombinefunction to transform the parsed values and perform additional validations between the parsed fields.The key concepts to understand here are where the view and validation logic for fields lives.
The
Form'sviewfunction is responsible for combining the rendered Fields, but theFieldcontains the information for how to display the form field itself (details like like<input type="date" />,<input type="checkbox" />,<textarea>etc.). Since form fields contain both display logic that changes how we parse/validate the field, all of the parsing and validation logic related to displaying the Field is also defined withFieldtype. For example,Field.withMincontains information that is used both for displaying the form field and for validating it. When we setField.withMin, it gives the Browser information on how to restrict the date picker UI from showing invalid dates, but setting that minimum value also runs that validation when we run the Form parser, even if we run it on a server through code sharing.Note that the validations in a
Fields definition (such asField.withMin, orField.date, etc.) are run regardless of whether you use that field in the Form'scombinefunction.