Elm 具有可组合形式的动态形式

Elm 具有可组合形式的动态形式,elm,Elm,我正在尝试使用实现Elm 0.19中的动态表单 我收到一个带有字段、字段描述等的json,所以我事先不知道它将包含多少字段 因此,定义表单的传统方式是: Form.succeed OutputValues |> Form.append field1 |> Form.append field2 不起作用,因为我事先不知道OutputValues结构 我看到有一个函数Form.list,它看起来是一个很有前途的路径,尽管它似乎期望所有字段都相等,但我的情况并非如

我正在尝试使用实现Elm 0.19中的动态表单

我收到一个带有字段、字段描述等的json,所以我事先不知道它将包含多少字段

因此,定义表单的传统方式是:

Form.succeed OutputValues
      |> Form.append field1
      |> Form.append field2
不起作用,因为我事先不知道
OutputValues
结构

我看到有一个函数
Form.list
,它看起来是一个很有前途的路径,尽管它似乎期望所有字段都相等,但我的情况并非如此,例如,我可能有一个文本字段和一个选择字段

这个图书馆有没有直接的方法?
谢谢。

表单库并不明确支持您尝试执行的操作,但我们可以让它正常工作

太长,读不下去了 下面是我的示例,说明如何获取JSON并创建表单:

怎么去那里
Form.list
无疑是一条有前途的道路。您也完全正确,
Form.list
要求所有字段的类型都相同。让我们从这里开始吧!我们可以创建一个数据结构,通过创建自定义类型来保存它们。在我的示例中,我将其称为
DynamicFormFieldValue
。我们将为每种字段制作一个变体。我为文本、整数和选择列表创建了一个。每一个都需要保存字段的值和所有附加值(如标题和默认值),以使其很好地显示出来。这就是我们将JSON解码成的内容,表单值是什么,表单输出是什么。结果类型如下所示:

type alias TextFieldRequirements =
    { name : String
    , default : Maybe String
    }


type alias IntFieldRequirements =
    { name : String
    , default : Maybe Int
    }


type alias SelectFieldRequirements =
    { name : String
    , default : Maybe String
    , options : List ( String, String )
    }


type DynamicFormFieldValue
    = TextField String TextFieldRequirements
    | IntField Int IntFieldRequirements
    | SelectField String SelectFieldRequirements
dynamicFormField : Int -> Form DynamicFormFieldValue DynamicFormFieldValue
dynamicFormField fieldPosition =
    Form.meta
        (\field ->
            case field of
                TextField textValue ({ name } as requirements) ->
                    Form.textField
                        { parser = \_ -> Ok field
                        , value = \_ -> textValue
                        , update = \value oldValue -> TextField value requirements
                        , error = always Nothing
                        , attributes =
                            { label = name
                            , placeholder = ""
                            }
                        }

                IntField intValue ({ name } as requirements) ->
                    Form.numberField
                        { parser = \_ -> Ok field
                        , value = \_ -> String.fromInt intValue
                        , update = \value oldValue -> IntField (Maybe.withDefault intValue (String.toInt value)) requirements
                        , error = always Nothing
                        , attributes =
                            { label = name
                            , placeholder = ""
                            , step = Nothing
                            , min = Nothing
                            , max = Nothing
                            }
                        }

                SelectField selectValue ({ name, options } as requirements) ->
                    Form.selectField
                        { parser = \_ -> Ok field
                        , value = \_ -> selectValue
                        , update = \value oldValue -> SelectField value requirements
                        , error = always Nothing
                        , attributes =
                            { label = name
                            , placeholder = ""
                            , options = options
                            }
                        }
        )

要显示表单,您只需要一个函数,该函数可以接受表单值并显示适当的表单小部件。表单库提供了
form.meta
来根据值更改表单。因此,我们将在自定义类型上进行模式匹配,并返回
Form.textField
Form.numberField
,或
Form.selectField
。大概是这样的:

type alias TextFieldRequirements =
    { name : String
    , default : Maybe String
    }


type alias IntFieldRequirements =
    { name : String
    , default : Maybe Int
    }


type alias SelectFieldRequirements =
    { name : String
    , default : Maybe String
    , options : List ( String, String )
    }


type DynamicFormFieldValue
    = TextField String TextFieldRequirements
    | IntField Int IntFieldRequirements
    | SelectField String SelectFieldRequirements
dynamicFormField : Int -> Form DynamicFormFieldValue DynamicFormFieldValue
dynamicFormField fieldPosition =
    Form.meta
        (\field ->
            case field of
                TextField textValue ({ name } as requirements) ->
                    Form.textField
                        { parser = \_ -> Ok field
                        , value = \_ -> textValue
                        , update = \value oldValue -> TextField value requirements
                        , error = always Nothing
                        , attributes =
                            { label = name
                            , placeholder = ""
                            }
                        }

                IntField intValue ({ name } as requirements) ->
                    Form.numberField
                        { parser = \_ -> Ok field
                        , value = \_ -> String.fromInt intValue
                        , update = \value oldValue -> IntField (Maybe.withDefault intValue (String.toInt value)) requirements
                        , error = always Nothing
                        , attributes =
                            { label = name
                            , placeholder = ""
                            , step = Nothing
                            , min = Nothing
                            , max = Nothing
                            }
                        }

                SelectField selectValue ({ name, options } as requirements) ->
                    Form.selectField
                        { parser = \_ -> Ok field
                        , value = \_ -> selectValue
                        , update = \value oldValue -> SelectField value requirements
                        , error = always Nothing
                        , attributes =
                            { label = name
                            , placeholder = ""
                            , options = options
                            }
                        }
        )

在库中连接此显示功能有点笨拙<代码>表单.列表的设计没有考虑用例。我们希望列表保持相同的长度,只需迭代即可。为了实现这一点,我们将删除“添加”和“删除”按钮,并强制提供一个虚拟的默认值(永远不会使用)


希望ellie示例能够演示其余内容,您可以根据自己的需要进行调整

此外,如果某些字段是必填字段或非必填字段,也可以按如下所示进行处理: