I have a form in which the user can either select from a pre-existing list of values, or create a new (Text) value.
What will be the most elegant way to code that?
My best (and IMO not so elegant) way of doing so was by defining:
data MyInput = MyInput {createNew :: Bool, newVal :: Maybe Text, existingVal :: Maybe Text}
myForm :: [(Text,Text)] -> Html -> MForm MySite MySite (FormResult MyInput,Widget)
myForm exisingVals = renderTable $ MyInput
<$> areq boolField "Create new" (Just False)
<*> aopt textField "New val" Nothing
<*> aopt (selectField existingVals) "Existing values" Nothing
And once the form is received, pass the result through something like:
getMyValue :: MyInput -> Either ErrorMsg Text
getMyValue i = if createNew i
then if newVal i == Nothing || existingVal i /= Nothing
then Left "Missing new value or illegal input"
else Right . fromJust . newVal $ i
else if existingVal i == Nothing || newVal i /= Nothing
then Left "Missing selection or illegal input"
else Right . fromJust . existingVal $ i
And have the handler decide whether to re-send the form, or proceed according to the result.
Any better/shorter suggestions?
My real form has two such select/create fields, which makes the data structure and processing even more tedious.
Thanks,
You can factor out the common code, use pattern matching and guards, and generalize with a higher-order-function that accepts the accessor functions: