Elm - 在 Elm 中动态更新字段

kay*_*yne 2 elm

我复制了这段代码,以便任何人都可以尝试一下http://elm-lang.org/try

import Html exposing (..)
import Html.App as App
import Html.Attributes exposing (..)
import Html.Events exposing (..)


main =
  App.program
  { init = init
  , view = view
  , update = update
  , subscriptions = \_ -> Sub.none
  }


init =
  ( { posts = [], newPost = { title = "", slug = "" } }, Cmd.none )


type alias Post =
  { title : String
  , slug : String
  }


type alias Model =
  { posts : List Post
  , newPost : Post
  }


type Msg
  = NoOp
  | NewPostField Post String String


update msg model =
  case msg of

    NoOp ->
      ( model, Cmd.none )

    NewPostField currentPost field newValue ->
      case field of

        "title" ->
          ( { model | newPost = { slug = currentPost.slug, title = newValue } }, Cmd.none )

        "slug" ->
          ( { model | newPost = { slug = newValue, title = currentPost.title } }, Cmd.none )

       -- The problem is here, I have to repeat this process for every field

        _ ->
          ( model, Cmd.none )


view model =
  div []
    [ h1 [] [ text ("title : " ++ model.newPost.title ++ " | slug : " ++ model.newPost.slug) ]
    , input [ onInput (NewPostField model.newPost "title"), placeholder "Title" ] []
    , input [ onInput (NewPostField model.newPost "slug"), placeholder "Slug" ] []
    , button [] [ text "Save" ]
  ]
Run Code Online (Sandbox Code Playgroud)

我将字段最小化为两个(标题和标题),但还有其他字段,例如:内容、摘录......

无论如何,我可以在不为所有字段创建案例的情况下更新记录,例如仅更新必要的字段而不遍历所有字段?

mar*_*gio 5

我会在您的代码中更改以下内容:

如果您对每个操作都有特定的消息,那么您可以拥有更多的清洁功能updateview功能。编译器还将帮助您检查是否处理了所有情况,并且没有传递无意义的参数。

type Msg
  = NoOp
  | NewPostTitle Post String
  | NewPostSlug Post String
Run Code Online (Sandbox Code Playgroud)

这不会节省您太多的打字时间,但您的结果update将如下所示。请注意,您不再有嵌套模式匹配。另请注意更新记录的语法,一次更新一个字段。

update msg model =
  case msg of
    NoOp ->
      ( model, Cmd.none )
    NewPostTitle currentPost value ->
      ( { model | newPost = { currentPost | title = value } }, Cmd.none )
    NewPostSlug currentPost value ->
      ( { model | newPost = { currentPost | slug = value } }, Cmd.none )
Run Code Online (Sandbox Code Playgroud)

最后,在您看来,您不必传递字符串参数,这使得代码更加简洁。但真正重要的部分是现在它是类型安全的。

view model =
  div []
    [ h1 [] [ text ("title : " ++ model.newPost.title ++ " | slug : " ++ model.newPost.slug) ]
    , input [ onInput (NewPostTitle model.newPost), placeholder "Title" ] []
    , input [ onInput (NewPostSlug model.newPost), placeholder "Slug" ] []
    , button [] [ text "Save" ]
  ]
Run Code Online (Sandbox Code Playgroud)