首页 > 解决方案 > 如何在 IHP 表单中传递 List 参数?

问题描述

我正在尝试在 IHP 中的表格中进行多项选择。目前试图在视图中使用多个类似这样的复选框来解决它。

renderIngredientSelection :: Ingredient -> Html
renderIngredientSelection ingredient = [hsx|
    <li>
        <input name="ingredients" type="checkbox" value={(get #name ingredient)} />{get #name ingredient}
    </li>
    |]

所以网络日志的浏览器工具说它正在正确地发送这样的请求。

barcode=5555555555555&name=Pancake&ingredients=milk&ingredients=egg

但在控制器中,该param函数只会捕获第一个ingredients参数。

有没有办法在控制器中捕获所有这些参数?我在网络日志中看到,创建了一个包含所有参数的元组列表,包括两个ingredients参数。我怎样才能访问它并将其映射到类似的列表中["milk", "egg"]

标签: haskellihp

解决方案


您可以使用它allParams来访问您在日志中看到的完整请求参数。

对于像这样的请求:

barcode=5555555555555&name=Pancake&ingredients=milk&ingredients=egg

我们可以allParams这样使用:

action MyAction = do
    let ingredients = allParams
    -- ingredients = [("barcode",Just "5555555555555"),("name",Just "Pancake"),("ingredients",Just "milk"),("ingredients",Just "egg")]

我们仍然需要过滤此列表以仅返回成分值:

action MyAction = do
    let ingredients = allParams
        |> filter (\(paramName, paramValue) -> paramName == "ingredients")
    -- ingredients = [("ingredients",Just "milk"),("ingredients",Just "egg")]

现在我们需要将此键值映射映射到值。因为值是可能(如Just "milk"),我们将使用mapMaybe而不是mapmapMaybe丢弃所有Nothing值并解包Just

action MyAction = do
    let ingredients = allParams
        |> filter (\(paramName, paramValue) -> paramName == "ingredients")
        |> mapMaybe (\(paramName, paramValue) -> paramValue)
    -- ingredients = ["milk", "ingredients"]

我们有一个[ByteString]现在。我们处理的大多数函数都期望 aText而不是 a ByteString,因此让我们使用cs (cs 是转换字符串的缩写) 进行转换

action MyAction = do
    let ingredients :: [Text] = allParams
        |> filter (\(paramName, paramValue) -> paramName == "ingredients")
        |> mapMaybe (\(paramName, paramValue) -> paramValue)
        |> map cs
    -- ingredients = ["milk", "ingredients"]

将其移至Application/Controller/Helper.hs

对于一个很好的代码结构,我会将此函数移出Application/Controller/Helper.hs如下:

module Application.Helper.Controller
( ...
, paramList -- Don't forget the export :)
)

paramList name = allParams
        |> filter (\(paramName, paramValue) -> paramName == name)
        |> mapMaybe (\(paramName, paramValue) -> paramValue)
        |> map cs

然后像这样在控制器中使用它:

action MyAction = do
    let ingredients = paramList "ingredients"

中的所有功能Application.Helper.Controller都在我们的控制器中自动可用。


推荐阅读