Skip to content

Instantly share code, notes, and snippets.

@farzadbekran
Created January 10, 2022 06:06
Show Gist options
  • Save farzadbekran/e51f37a49cee00ce3d65545c9a5a9ae2 to your computer and use it in GitHub Desktop.
Save farzadbekran/e51f37a49cee00ce3d65545c9a5a9ae2 to your computer and use it in GitHub Desktop.
Formless 3 Type problem
module App.Component.Forms.Test where
import Prologue
import Data.Int as Int
import Formless as F
import Halogen as H
import Halogen.HTML as HH
import Halogen.HTML.Events as HE
import Halogen.HTML.Properties as HP
type Form :: (Type -> Type -> Type -> Type) -> Row Type
type Form f
= ( name :: f String String String
, nickname :: f String Void (Maybe String)
, age :: f String String Int
)
type FormInputs
= { | Form F.FieldInput }
type Cat
= { | Form F.FieldOutput }
type Query
= Const Void
type Input
= Unit
type Output
= Cat
type FormContext
= F.FormContext (Form F.FieldState) (Form (F.FieldAction Action)) Input Action
type FormlessAction
= F.FormlessAction (Form F.FieldState)
data Action
= Receive FormContext
| Eval FormlessAction
type State
= FormContext
form :: H.Component Query Input Output Aff
form =
F.formless { liftAction: Eval } mempty
$ H.mkComponent
{ initialState: \context -> context
, render
, eval:
H.mkEval
$ H.defaultEval
{ receive = Just <<< Receive
, handleAction = handleAction
, handleQuery = handleQuery
}
}
where
render :: FormContext -> H.ComponentHTML Action () Aff
render { formActions, fields, actions } =
HH.form
[ HE.onSubmit formActions.handleSubmit ]
[ HH.div_
[ HH.label_ [ HH.text "Name" ]
, HH.input
[ HP.type_ HP.InputText
, HP.placeholder "Scooby"
, HP.value fields.name.value
, HE.onValueInput actions.name.handleChange
, HE.onBlur actions.name.handleBlur
]
-- We can use the `result` field to check if we have an error
, case fields.name.result of
Just (Left error) -> HH.text error
_ -> HH.text ""
]
]
handleAction ::
Action ->
H.HalogenM State Action () (F.FormOutput Output) Aff Unit
handleAction = case _ of
Receive context -> H.put context
Eval action -> F.eval action
handleQuery ::
forall a.
F.FormQuery _ _ _ _ a ->
H.HalogenM State Action () (F.FormOutput Output) Aff (Maybe a)
handleQuery = do
let
validateName :: String -> Either String String
validateName input
| input == "" = Left "Required"
| otherwise = Right input
validateNickname :: String -> Either Void (Maybe String)
validateNickname input
| input == "" = Right Nothing
| otherwise = Right (Just input)
validateAge :: String -> Either String Int
validateAge input = case Int.fromString input of
Nothing -> Left "Not a valid integer."
Just n
| n > 20 -> Left "No dog is over 20 years old!"
| n <= 0 -> Left "No dog is less than 0 years old!"
| otherwise -> Right n
validation :: { | Form F.FieldValidation }
validation =
{ name: validateName
, nickname: validateNickname
, age: validateAge
}
handleSuccess :: Cat -> H.HalogenM _ _ _ _ _ Unit
handleSuccess = F.raise
F.handleSubmitValidate handleSuccess F.validate validation
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment