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

How can I pass List params in IHP forms?

我正在尝试在 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"]?

这样的列表中

您可以使用 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")]

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

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

现在我们需要将此 key-value-map 映射到值。因为该值是一个可能(如 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]。我们正在处理的大多数函数都期望 Text 而不是 ByteString,因此让我们使用 cs (cs 是转换字符串的缩写)[=54 进行转换=]:

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中的所有功能在我们的控制器中自动可用。