I am trying to make a multiple selection part of my form in IHP. Currently trying to solve it with multiple checkboxes about like this in the View.
renderIngredientSelection :: Ingredient -> Html
renderIngredientSelection ingredient = [hsx|
<li>
<input name="ingredients" type="checkbox" value={(get #name ingredient)} />{get #name ingredient}
</li>
|]
So the browser tool of the network log says it's properly sending a request like this.
barcode=5555555555555&name=Pancake&ingredients=milk&ingredients=egg
But in the controller, the param
function will only catch the first ingredients
parameter.
Is there any way to catch all these parameters in the controller? I see in the network log, there is created a list of tuples containing all the parameters, including both the ingredients
parameters. How could I access this and map it into a list like ["milk", "egg"]
?
You can use
allParams
to access the full request parameters you see in the logs.For a request like:
We can use the
allParams
like this:We still need to filter this list to only return the ingredients values:
Now we need to map this key-value-map to only the values. Because the value is a maybe (like
Just "milk"
), we'll usemapMaybe
instead ofmap
.mapMaybe
throws away all theNothing
values and unpacks theJust
:We have a
[ByteString]
now. Most functions we're dealing with expect aText
instead of aByteString
, therefore let's do a conversion usingcs
(cs is short for convert string):Moving it to
Application/Controller/Helper.hs
For a nice code structure I'd move this function out to
Application/Controller/Helper.hs
like this:And then use it in the controller like this:
All the functions in
Application.Helper.Controller
are automatically available in our controllers.