如何在 IHP 表单中传递 List 参数?

Lar*_*tad 7 haskell ihp

我正在尝试在 IHP 中制作表单的多项选择部分。目前正在尝试在视图中使用多个类似这样的复选框来解决它。

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

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

barcode=5555555555555&name=Pancake&ingredients=milk&ingredients=egg
Run Code Online (Sandbox Code Playgroud)

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

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

小智 6

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

对于像这样的请求:

barcode=5555555555555&name=Pancake&ingredients=milk&ingredients=egg
Run Code Online (Sandbox Code Playgroud)

我们可以这样使用allParams

barcode=5555555555555&name=Pancake&ingredients=milk&ingredients=egg
Run Code Online (Sandbox Code Playgroud)

我们仍然需要过滤这个列表以只返回成分值:

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

现在我们需要将此键值映射仅映射到值。因为该值是一个可能(例如Just "milk"),所以我们将使用mapMaybe代替mapmapMaybe丢弃所有Nothing值并解压Just

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

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

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

将其移至 Application/Controller/Helper.hs

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

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

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

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

paramList name = allParams
        |> filter (\(paramName, paramValue) -> paramName == name)
        |> mapMaybe (\(paramName, paramValue) -> paramValue)
        |> map cs
Run Code Online (Sandbox Code Playgroud)

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