如何在Elm中处理来自递归HTML UI的消息?

问题描述 投票:1回答:1

我正在尝试构建一个允许用户操纵递归数据结构的UI。例如,想象一个可视化模式编辑器或数据库表编辑器,其中您具有普通的旧类型(字符串和整数)以及由这些普通类型(数组,结构)组成的复合类型。在下面的示例中,Struct_类似于JavaScript对象,其中的键是字符串,值是任何类型,包括嵌套的Array_ s和Struct_ s。

-- underscores appended to prevent confusion about native Elm types. These are custom to my application.
type ValueType
    = String_
    | Int_
    | Float_
    | Array_ ValueType
    | Struct_ (List (String, ValueType))

type alias Field =
    { id : Int
    , label : String
    , hint : String
    , hidden : Bool
    , valueType : ValueType
    }

type alias Schema = List Field

现在要为此构建一个UI,我可以创建一个简单的递归函数:

viewField : Field -> Html Msg
viewField field =
    div []
    [ input [ type_ "text", value field.label ] []
    , viewValueType field.valueType
    ]

viewValueType : ValueType -> Html Msg
viewValueType valueType =
    let
        structField : (String, ValueType) -> Html Msg
        structField (key, subtype) =
            div []
                [ input [type_ "text", placeholder "Key", value key, onInput EditStructSubfieldKey] []
                , viewValueType subtype
                ]

        options : List(Html Msg)
        options = case valueType of
            String_ -> -- string ui
            Int_ -> -- int ui
            Float_ -> -- float ui
            Array_ subtype ->
                [ label [] [ text "subtype" ]
                , viewValueType subtype
                ]
            Struct_ fields ->
                [ label [] [ text "subfields" ]
                , List.map structField fields
                , button [ onClick AddStructSubfield ] [ text "Add subfield" ]
                ]
    in
    div [] options

当尝试使用此递归结构操纵我的状态时,就会出现我的问题。 Msg中的哪种数据结构可以容纳用户对该结构的编辑,添加新字段,子字段以及编辑其属性?如何在update循环中正确解码?

例如...

type alias Model =
    { fields : List Field }

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
    case msg of
        AddStructSubfield _???_ ->
            ({model | fields = ???}, Cmd.none)
        EditStructSubfieldKey _???_ ->
            ({model | fields = ???}, Cmd.none)

[您将附加到AddStructSubfieldEditStructSubfieldKey消息(随同onClick处理程序传递给上述button的消息)什么样的数据,以正确更新您的状态,特别是当说Struct_时,嵌套在另一个Struct_中,嵌套在Array_中?例如,EditStructSubfieldKey将仅包含用户输入的新字符串,但没有足够的信息来解决嵌套的项目。

recursion functional-programming elm
1个回答
0
投票

我们在代码库中完全做到了这一点,但是还没有开源支持该功能的'库'。但是,对于您的问题的答案是,您需要在代码和消息中添加Path的概念。

type Path 
    = Field: String 
    | Index: Int 

然后,当您下降[Field "f1", Index 3, ...]时,您的视图必须不断更新路径,并且您的更新功能需要通过插入,删除...来支持,这些插入,删除,...采用路径和现有结构并返回给您新的结构。] >

© www.soinside.com 2019 - 2024. All rights reserved.