在 Elm 的数据列表中创建新记录

Create a New Record in a List of data in Elm

我在 Elm 中完成了从 API 加载资源,一切都很好...除了一个小问题:我不知道如何在不保留它的情况下更新或创建新记录。

我有一个 Msg 类型(我为这个演示剥离了一些代码)

type Msg
  = NoOp
  | FetchSucceed (List User)
  | FetchError Http.Error
  | UpdateTitle String
  | ...



update msg model =
  case model of
     NoOp ->
       ( model, Cmd.none )

     FetchSucceed newModel =
       ( { model | users = newModel, isLoading = False }, Cmd.none )

     FetchError _ =
       ( { model | isLoading = False }, Cmd.none )

     UpdateTitle newTitle =
       -- I don't know what to put here, the previous messages
       -- have a list, and I Just want to add ONE model


view model =
  div []
    [ List.map displayRow model.users
    , formCreateUser {title = "", username = "", email = ""}
    ]

formCreateUser user =
  div []
    [ input [ onInput UpdateTitle, placeholder "Title" ] []
    , button [ onClick SaveUser ] [ text "Save" ]
    ]

我希望能够从此表单 (formCreateUser) 添加新模型,但我不断收到此错误:

The 3rd element has this type:
  VirtualDom.Node Msg

But the 4th is:     
  Html Link -> Html (String -> Msg)

edit2:添加一些上下文

如果我理解你的示例片段,你有一个显示现有用户列表的页面,并且你想要一个 "quick add" 表单,让你创建另一个仅给出标题的用户。我将举一个简单的例子来说明如何实现这一目标,希望它能对您 运行 遇到的问题有所启发。

我假设您的用户和模型目前看起来像这样:

type alias Model =
  { users : List User
  , isLoading : Bool
  }

type alias User =
  { title : String
  , username : String
  , email : String
  }

既然你有那个快速添加表单,我认为你不想在他们点击提交之前添加新用户。记住这个概念,让我们更新模型以存储待处理的新用户标题:

type alias Model =
  { users : List User
  , isLoading : Bool
  , newUserTitle : Maybe String
  }

现在我们可以相应地更改您的视图功能。由于我们要在文本框中显示键入的标题,所以我们将 formCreateUser 更改为:

formCreateUser model =
  div []
    [ input [ onInput UpdateTitle, placeholder "Title", value (Maybe.withDefault "" model.newUserTitle) ] []
    , button [ onClick SaveUser ] [ text "Save" ]
    ]

也就是说view中的调用代码也需要更新:

view model =
  div []
    [ div [] (List.map displayRow model.users)
    , formCreateUser model
    ]

现在我们需要处理 UpdateTitle 消息以在键入时设置内容:

 UpdateTitle newTitle ->
   ( { model | newUserTitle = Just newTitle }, Cmd.none )

现在我们还可以处理提交按钮。这是您创建新用户并将其附加到现有用户列表的地方:

 SaveUser ->
   case model.newUserTitle of
     Nothing -> (model, Cmd.none)
     Just title ->
       ( { model
           | newUserTitle = Nothing
           , users = model.users ++ [{ title = title, username = "", email = "" }]
           }, Cmd.none)

如果您希望 SaveUser 将其提交到您的 API 端点,您还可以 return 一个合适的 Cmd,但这似乎超出了您的范围问题。

虽然这一切都不是处理您的情况的理想方式,但希望这种解释能让您更好地理解此类事情所需的构建块。我已经发布了 full gist here which can be pasted and run in elm-lang.org/try.