primait/pyxis-components/6.0.0

NOTE: the latest version is 9.0.3

Prima.Pyxis.Form

Allows to create a Form and it's fields using predefined Html syntax.

Form Configuration

type Form model msg

Public Form data type, it can be created with init function

type alias Label =
String

Alias for String. Useful to have easy-to-read signatures.

type alias Slug =
String

Alias for String. Useful to have easy-to-read signatures.

type alias Value =
String

Alias for String. Useful to have easy-to-read signatures.

Form Configuration Helpers

Creates an empty form with given Validation Visibility Policy in Pristine status (untouched).

setAsTouched : Form model msg -> Form model msg

Sets the form to Touched state (Not Pristine but not yet Submitted).

setAsSubmitted : Form model msg -> Form model msg

Sets the form to Submitted state.

addField : FormField model msg -> Form model msg -> Form model msg

Adds a FormField to the form.

--
import Prima.Pyxis.Form as Form
import Prima.Pyxis.Form.Event as Event
import Prima.Pyxis.Form.Validation as FormValidation


...


type alias Model =
    { data : FormData
    , form : Form FormData Msg
    }


type alias FormData =
    { username : Maybe String
    }


type Msg
    = UpdateUsername (Maybe String)


...


usernameField : FormField FormData Msg
usernameField =
    Form.textConfig
        -- Field Slug
        "username"
        -- Label
        (Just "Username")
        -- Data attributes
        [ minlength 3, maxlength 12 ]
        -- FormData accessor
        .username
        -- Event -> Msg mappings
        [ Event.onInput UpdateUsername ]
        -- Form Validations
        [ FormValidation.config FormValidation.Error
          (\formData -> Maybe.withDefault False <| Maybe.map ((<) 3 << String.length) formData.username)
          "Username must be greater than 3 digits"
        ]


...


view : Model -> Html Msg
view ({ form } as model) =
    form
        |> Form.addField usernameField
        |> Form.render
addFieldList : FormFieldList model msg -> Form model msg -> Form model msg

Adds a Field Group to the form

--
...
formFieldList : FormFieldList FormData Msg
formFieldList =
    Form.fieldListConfig
        -- Field Group label
        "Username & Alternative Username"
        -- Field Group FormFields
        [ username, alternativeUsername ]
        -- Field Group own validations
        [ FormValidation.config FormValidation.Warning
            (\formData -> not (formData.username == formData.alternativeUsername))
            "Username and password shouldn't be equal"
        ]
...
view : Model -> Html Msg
view ({ form } as model) =
    form
        |> Form.addFieldList formFieldList
        |> Form.render
addCustomRow : Html msg -> Form model msg -> Form model msg

Adds a custom Html msg in a form. It's not wrapped in a-form-field and doesn't provide validations

Form State Helpers

isFormSubmitted : Form model msg -> Bool

Checks if the Form state is Submitted.

isFormPristine : Form model msg -> Bool

Checks if the Form state is Pristine.

isFormTouched : Form model msg -> Bool

Checks if the Form state is Touched.

InputGroup

prepend : List (Html msg) -> FormField model msg -> FormField model msg

Creates an InputGroup prepending a given List(Html msg) to a given FormField

--
...
dateOfBirth : FormData -> Html Msg -> Form.InputGroup FormData Msg
dateOfBirth { isVisibleDP, dateOfBirthDP } prependable =
    Form.datepickerConfig
        "date_of_birth"
        (Just "Date of Birth")
        []
        .dateOfBirth
        (UpdateDatePicker DateOfBirth)
        [ Event.onInput (UpdateField DateOfBirth) ]
        dateOfBirthDP
        isVisibleDP
        [ FormValidation.config FormValidation.Error
            (\formData -> not (formData.dateOfBirth == Nothing))
            "You must select a date"
        ]|> Form.prepend [ prependable ]
append : List (Html msg) -> FormField model msg -> FormField model msg

Creates an InputGroup appending a given List(Html msg) to a given FormField

--
...
dateOfBirth : FormData -> Html Msg -> Form.InputGroup FormData Msg
dateOfBirth { isVisibleDP, dateOfBirthDP } appendable =
    Form.datepickerConfig
        "date\_of\_birth"
        (Just "Date of Birth")
        []
        .dateOfBirth
        (UpdateDatePicker DateOfBirth)
        [ Event.onInput (UpdateField DateOfBirth) ]
        dateOfBirthDP
        isVisibleDP
        [ FormValidation.config FormValidation.Error
        (\formData -> not (formData.dateOfBirth == Nothing))
        "You must select a date"
        ]
        |> Form.append [ appendable ]

Validation Visibility Policy

= Always
| WhenSubmitted

Specify when the form will show validations.

  • Always: validations display will depend only on validation function result.
  • WhenSubmitted: validations will be shown only after setAsSubmitted have been called

Form Validation Visibility Policy Helpers

Returns form's Validation Visibility Policy

validateAlways : Form model msg -> Form model msg

Sets the form validation visibility policy to Always

validateWhenSubmitted : Form model msg -> Form model msg

Sets the form validation visibility policy to WhenSubmitted

Fields Configuration

type FormField model msg

Represents the configuration of a single form field.

addTooltipToFieldWhen : Bool -> Config msg -> FormField model msg -> FormField model msg

Adds a Pyxis tooltip to a given FormField

FieldList Configuration

type FormFieldList model msg

It's a collection of form fields rendered together in a single row

Label
-> List (FormField model msg)
-> List (Validation model)
-> FormFieldList model msg

Configure a FormFieldList

Bool
-> Config msg
-> FormFieldList model msg
-> FormFieldList model msg

Adds a Pyxis tooltip to a given Field List

Input

Slug
-> Maybe Label
-> List (Attribute msg)
-> (model -> Maybe Value)
-> List (Event msg)
-> List (Validation model)
-> FormField model msg

Creates an input text field. This field can handle only onInput, onFocus, onBlur events. Other events will be ignored.

--
import Prima.Pyxis.Form as Form exposing (FormField)
import Prima.Pyxis.Form.Event as Event
import Prima.Pyxis.Form.Validation as FormValidation


...


type alias Msg
    = OnInput (Maybe String)
    | OnFocus
    | OnBlur


type alias Model =
    { username : Maybe String }


...


usernameConfig : FormField Model Msg
usernameConfig =
    Form.textConfig
        "username"
        (Just "Username")
        [ minlength 3, maxlength 12 ]
        .username
        [ Event.onInput OnInput
        , Event.onFocus OnFocus
        , Event.onBlur OnBlur
        ]
        [ FormValidation.config FormValidation.Error
          (\formData -> not (formData.username == Nothing))
          "Username shouldn't be empty"
        ]
Slug
-> Maybe Label
-> List (Attribute msg)
-> (model -> Maybe Value)
-> List (Event msg)
-> List (Validation model)
-> FormField model msg

Creates a password text field. Same configuration as textConfig.

Slug
-> Maybe Label
-> List (Attribute msg)
-> (model -> Maybe Value)
-> List (Event msg)
-> List (Validation model)
-> FormField model msg

Creates a texarea field. Same configuration as textConfig.

Checkbox

Slug
-> Maybe Label
-> List (Attribute msg)
-> (model -> List ( Slug, Bool ))
-> List (Event msg)
-> List CheckboxOption
-> List (Validation model)
-> FormField model msg

Creates a checkbox field. This field can handle only onCheck event. Other events will be ignored.

--
import Prima.Pyxis.Form as Form exposing (FormField, Label, Slug, CheckboxOption)
import Prima.Pyxis.Form.Event as Event
import Prima.Pyxis.Form.Validation as FormValidation


...


type alias Msg
    = OnCheck ( Slug, Bool )


type alias Model =
    { country : Maybe String
    , countries: List (Label, Slug, Bool)
    }


...


countries : Model -> FormField Model Msg
countries model =
    let
        reader : (Model -> List (Slug, Bool))
        reader =
            (List.map (\( _, slug, checked ) -> ( slug, checked )) << .countries)


        options : List CheckboxOption
        options =
            List.map (( label, slug, isChecked ) -> Form.checkboxOption label slug isChecked) model.countries
    in
    Form.checkboxConfig
        "countries"
        (Just "Countries")
        []
        reader
        [ Event.onCheck OnCheck ]
        options
        []
checkboxOption : Label -> Slug -> Bool -> CheckboxOption

Creates a checkbox option.

Radio

Slug
-> Maybe Label
-> List (Attribute msg)
-> (model -> Maybe Value)
-> List (Event msg)
-> List RadioOption
-> List (Validation model)
-> FormField model msg

Creates a radio field. This field can handle only onSelect event. Other events will be ignored.

--
import Prima.Pyxis.Form as Form exposing (FormField, RadioOption)
import Prima.Pyxis.Form.Event as Event


...


type alias Msg
    = OnSelect (Maybe String)


type alias Model =
    { gender : Maybe String }


...


genderConfig : FormField Model Msg
genderConfig =
    let
        options : List RadioOption
        options =
            [ Form.radioOption "Male" "male", Form.radioOption "Female", "female" ]
    in
    Form.radioConfig
        "gender"
        (Just "Gender")
        []
        .gender
        [ Event.onSelect OnSelect ]
        options
        []
radioOption : Label -> Slug -> RadioOption

Creates a radio option.

Select

Slug
-> Maybe Label
-> Bool
-> Bool
-> Maybe String
-> List (Attribute msg)
-> (model -> Maybe Value)
-> List (Event msg)
-> List SelectOption
-> List (Validation model)
-> FormField model msg

Creates a select field. This field is a custom component on desktop devices. It fallbacks to a native Html Select tag on mobile devices. Infact we need to express isDisabled flag as an Html Attribute and also as a parameter for this method.

This field can handle only onToggle, onInput, onSelect, onFocus and onBlur events. Other events will be ignored.

--
import Prima.Pyxis.Form as Form exposing (FormField, Label, Slug, SelectOption)
import Prima.Pyxis.Form.Event as Event
import Html.Attributes
...


type alias Msg
    = OnInput (Maybe String)
    | OnToggle
    | OnSelect (Maybe String)
    | OnFocus
    | OnBlur


type alias Model =
    { city : Maybe String
    , isOpen : Bool
    , isDisabled : Bool
    }


...


cities : Model -> FormField Model Msg
cities model =
    let
        options : List SelectOption
        options =
            [ Form.selectOption "Milan" "MI", Form.selectOption "Turin" "TO", Form.selectOption "Rome" "RO" ]
    in
    Form.selectConfig
        "city"
        (Just "City")
        model.isDisabled
        model.isOpen
        (Just "Select a city")
        [ Html.Attributes.disabled model.isDisabled ]
        .city
        [ Event.onToggle OnToggle, Event.onInput OnInput, Event.onSelect OnSelect, Event.onFocus, Event.onBlur ]
        options
        [ FormValidation.config FormValidation.Error
          (\formData -> not (formData.city == Nothing))
          "You must select a city"
        ]
selectOption : Label -> Slug -> SelectOption

Creates a select option.

Datepicker

Slug
-> Maybe Label
-> List (Attribute msg)
-> (model -> Maybe Value)
-> (Msg -> msg)
-> List (Event msg)
-> Model
-> Bool
-> List (Validation model)
-> FormField model msg

Creates a datepicker field. This field can handle only onInput event. Other events will be ignored.

--
import Prima.Pyxis.Form as Form exposing (FormField)
import Prima.Pyxis.Form.Event as Event
import Prima.Pyxis.DatePicker as DatePicker
...


type alias Msg
    = OnInput (Maybe String)
    | OnDatePickerChange DatePicker.Msg


type alias Model =
    { datePicker : DatePicker.Model
    , birthDate : Maybe String
    , isDatePickerOpen : Bool
    }


...


dateOfBirth : Model -> FormField Model Msg
dateOfBirth model =
    Form.datepickerConfig
        "birthdate"
        (Just "Date of Birth")
        []
        .birthDate
        OnDatePickerChange
        [ Event.onInput OnInput ]
        model.datePicker
        model.isDatePickerOpen
        []

Autocomplete

String
-> Maybe String
-> Bool
-> Maybe String
-> List (Attribute msg)
-> (model -> Maybe Value)
-> (model -> Maybe Value)
-> List (Event msg)
-> List AutocompleteOption
-> List (Validation model)
-> FormField model msg

Creates an autocomplete field. This field can handle only onSelect, onAutocompleteFilter, onFocus and onBlur events. Other events will be ignored.

--
import Prima.Pyxis.Form as Form exposing (FormField)
import Prima.Pyxis.Form.Event as Event
import Tuple
...


type alias Msg
    = OnSelect (Maybe String)
    | OnFilter (Maybe String)


type alias Model =
    { empireFilter : Maybe String
    , empire : Maybe String
    , isOpen : Bool
    }


...


empire : Model -> FormField Model Msg
empire model =
    let
        filter : String
        filter =
            Maybe.withDefault "" model.empireFilter


        options : List AutocompleteOption
        options =
            [ ("Roman Empire", "roman")
            , ("Ottoman Empire", "ottoman")
            , ("French Empire", "french")
            , ("British Empire", "british")
            ]
            |> List.filter (String.contains filter << Tuple.first)
            |> List.map (\(label, slug) -> Form.autocompleteOption label slug)
    in
    Form.autocompleteConfig
        "empire"
        (Just "empire")
        model.isOpen
        (Just "No results")
        []
        .empireFilter
        .empire
        [ Event.onAutocompleteFilter OnFilter, Event.onSelect OnSelect ]
        options
        []
autocompleteOption : Label -> Slug -> AutocompleteOption

Creates an autocomplete option.

Pure Html

String
-> List (Html msg)
-> List (Validation model)
-> FormField model msg

Creates a custom rendered FormField.

--
import Prima.Pyxis.Form as Form exposing (FormField)


...


loremIpsum : FormField Model Msg
loremIpsum =
    Form.pureHtmlConfig
        "custom-form-field"
        [ text "Lorem ipsum dolor sit amet" ]
        []

FormField Helpers

fieldIsValid : model -> FormField model msg -> Bool

Checks if a given field is valid. All validations are returning True

fieldHasError : model -> FormField model msg -> Bool

Checks if a given field has errors

fieldHasWarning : model -> FormField model msg -> Bool

Checks if a given field has warnings

fieldIsPristine : model -> FormField model msg -> Bool

Checks if a given field is in Pristine state (the value in the model is Nothing or empty)

fieldIsTouched : model -> FormField model msg -> Bool

Checks if a given field have been provided with some input

FormFieldList Helpers

fieldListIsValid : model -> FormFieldList model msg -> Bool

Checks if a given field group is in valid state

fieldListHasError : model -> FormFieldList model msg -> Bool

Checks if a given field group triggers errors (both own and field only ones)

fieldListHasOwnError : model -> FormFieldList model msg -> Bool

Checks if a given field group triggers own errors only (not form field ones)

fieldListHasFieldError : model -> FormFieldList model msg -> Bool

Checks if a given field group triggers form field errors (not field group ones)

fieldListHasWarning : model -> FormFieldList model msg -> Bool

Checks if a given field group triggers warnings (both own and field only ones)

fieldListHasOwnWarning : model -> FormFieldList model msg -> Bool

Checks if a given field group triggers own warnings only (not form field ones)

fieldListHasFieldWarning : model -> FormFieldList model msg -> Bool

Checks if a given field group triggers form field warnings (not field group ones)

Render

render : model -> Form model msg -> Html msg

Renders a form with all it's fields. Requires a Form model msg created via Form.init and Form.addFields.

renderField : Form model msg -> model -> FormField model msg -> Html msg

Renders a single FormField

--
import Html exposing (Html)
import Prima.Pyxis.Form as Form exposing (Form, FormField)
import FieldConfig exposing (usernameConfig)


...


type Msg
    = OnInput (Maybe String)


type alias Model =
    { form : Form FormData Msg
    , data : FormData
    }


type alias FormData =
    { username: Maybe String
    }


...


view : Model -> Html Msg
view { data, formConfig } =
    div
    [ class "a-container" ]
    [
        usernameConfig
            |> Form.renderField formConfig data
    ]
renderFieldList : Form model msg -> model -> FormFieldList model msg -> Html msg

Renders a single FormFieldList

--
...
formFieldList : FormFieldList FormData Msg
formFieldList =
    Form.fieldListConfig
        -- Field List label
        "Username & Alternative Username"
        -- Field List FormFields
        [ username, alternativeUsername ]
        -- Field List own validations
        [ FormValidation.config FormValidation.Warning
            (\formData -> not (formData.username == formData.alternativeUsername))
            "Username and password shouldn't be equal"
        ]
...
view : Model -> Html Msg
view { data, formConfig } =
    div
    [ class "a-container" ]
    [ Config.formFieldList
        |> Form.renderFieldList formConfig data
    ]