Build composable forms with your own custom fields.
This is the base of the composable-form package. It implements a composable Form
type that is not tied to any particular field.
In order to understand this module, you should be familar with the basic Form module
first.
Say you need to use a type of field that is not implemented in the the basic Form module.
The recommended way of doing this is to copy the source code of the basic Form module
into your own MyProject.Form module, and then use field and custom to
define new types of fields.
While copy-pasting code might sound like a bad idea, keep in mind that
the basic Form module does not contain much code at all! It is just a bunch of one-liners
that delegate to this base module. It is the perfect template to build your own form.
If that still does not convince you, you could start your own MyProject.Form module like this:
import Form.Base as Base
type alias Form values output =
Base.Form values output (Field values)
type Field
= None
succeed : output -> Form values output
succeed =
Base.succeed
-- Other useful operations you will probably want to use,
-- like append, andThen...Notice that we could avoid redefining succeed, append, and others, but that would force us to
import Form.Base every time we needed to use those operations with our brand new form.
Create functions that build forms that contain a single field with an API that is similar to
the basic Form module.
This function is meant to be partially applied, providing only the two first parameters to
obtain a function that expects the configuration for a particular type of field. See
FieldConfig.
For this, you only need to provide:
input of the field tells whether it is empty or not.Field to your own specific field type.For example, Form.textField could be implemented like this:
textField :
{ parser : String -> Result String output
, value : values -> Value String
, update : Value String -> values -> values
, attributes : TextField.Attributes
}
-> Form values output
textField =
Base.field { isEmpty = String.isEmpty } (Text TextRaw)Notice how the configuration record in textField is a FieldConfig.
Note: You can use TextField.form,
SelectField.form, and others to build fields that are already
present in Form.
Most form fields require configuration! FieldConfig allows you to specify how a
concrete field is validated and updated, alongside its attributes:
parser must be a function that validates the input of the field and produces a Result
of either:outputString describing a problemvalue defines how the Value of the field is obtained from the form valuesupdate defines how the current form values should be updated with a new field
Valueattributes represent the attributes of the fieldCreate a custom field with total freedom.
You only need to provide a function that given some values produces a FilledField.
You can check the custom fields example for some inspiration.
Represents a field on a form that has been filled with values.
It contains:
Like Form.succeed but not tied to a particular type of field.
Like Form.append but not tied to a particular type of field.
Like Form.andThen but not tied to a particular type of field.
Like Form.optional but not tied to a particular type of field.
Like Form.meta but not tied to a particular type of field.
Represents a filled form.
You can obtain this by using fill.
A
Formthat can contain any type offield.