Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/multi select field grouped #1830

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 33 additions & 19 deletions yesod-form/Yesod/Form/Fields.hs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ module Yesod.Form.Fields
, withRadioField
, checkboxesField
, checkboxesFieldList
, multiSelectField
, multiSelectField
, multiSelectFieldList
, Option (..)
, OptionList (..)
Expand Down Expand Up @@ -478,27 +478,41 @@ multiSelectFieldList = multiSelectField . optionsPairs
multiSelectField :: Eq a
=> HandlerFor site (OptionList a)
-> Field (HandlerFor site) [a]
multiSelectField ioptlist =
Field parse view UrlEncoded
multiSelectField ioptlist = Field{fieldParse=parse, fieldView=view, fieldEnctype=enctype}
where
parse [] _ = return $ Right Nothing
parse optlist _ = do
mapopt <- olReadExternal <$> ioptlist
case mapM mapopt optlist of
Nothing -> return $ Left "Error parsing values"
Just res -> return $ Right $ Just res
enctype = UrlEncoded

parse [] _ = return $ Right Nothing
parse optlist _ = do
mapopt <- olReadExternal . flattenOptionList <$> liftHandler ioptlist
return $ case mapM mapopt optlist of
Nothing -> Left "Error parsing values"
res -> Right res

view theId name attrs val isReq = do
opts <- fmap olOptions $ handlerToWidget ioptlist
let selOpts = map (id &&& (optselected val)) opts
[whamlet|
<select ##{theId} name=#{name} :isReq:required multiple *{attrs}>
$forall (opt, optsel) <- selOpts
<option value=#{optionExternalValue opt} :optsel:selected>#{optionDisplay opt}
|]
where
optselected (Left _) _ = False
optselected (Right vals) opt = (optionInternalValue opt) `elem` vals
opts <- liftHandler ioptlist
let
rendered = case val of
Left _ -> []
Right xs -> [optionExternalValue o | o <- olOptions $ flattenOptionList opts, x <- xs, x == optionInternalValue o]
optsel Nothing = Prelude.null rendered
optsel (Just opt) = optionExternalValue opt `elem` rendered

[whamlet|
$newline never
<select ##{theId} name=#{name} :isReq:required multiple *{attrs}>
$case opts
$of OptionList{olOptions}
$forall opt <- olOptions
<option value=#{optionExternalValue opt} :optsel (Just opt):selected>
#{optionDisplay opt}
$of OptionListGrouped{olOptionsGrouped}
$forall (groupLbl, iOpts) <- olOptionsGrouped
<optgroup label=#{groupLbl}>
$forall opt <- iOpts
<option value=#{optionExternalValue opt} :optsel (Just opt):selected>
#{optionDisplay opt}
|]

-- | Creates an input with @type="radio"@ for selecting one option.
radioFieldList :: (Eq a, RenderMessage site FormMessage, RenderMessage site msg)
Expand Down
2 changes: 1 addition & 1 deletion yesod-form/yesod-form.cabal
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cabal-version: >= 1.10
name: yesod-form
version: 1.7.6
version: 1.7.7
license: MIT
license-file: LICENSE
author: Michael Snoyman <[email protected]>
Expand Down