是否有一个很好的模式来处理榆树中的大量输入字段?
Is there a nice pattern for dealing with lots of input fields in elm?
elm 中是否有一种模式可以避免编写大量消息来更新模型子元素上的各个字段?
目前,我的代码如下所示,其中包含针对每个更改的输入的消息,然后是针对每个字段的一堆更新逻辑。我想要做的是有一条像 AChanged 这样的消息,它处理对 A 的任何 属性 的所有更改。通过更新生成消息的函数中的记录或通过传入字段名称然后使用它像在 Javascript.
中那样直接对记录执行更新
module Main exposing (Model)
import Browser exposing (Document, UrlRequest)
import Browser.Navigation as Nav exposing (Key)
import Html exposing (div, input)
import Html.Events exposing (onInput)
import Url exposing (Url)
type alias A =
{ a : String
, b : String
, c : String
, d : String
}
type alias B =
{ e : String
, f : String
, g : String
, h : String
}
type alias Model =
{ key : Nav.Key
, url : Url.Url
, a : A
, b : B
}
type Msg
= UrlChanged Url.Url
| LinkClicked Browser.UrlRequest
| AaChanged String
| AbChanged String
| AcChanged String
| AdChanged String
| BeChanged String
| BfChanged String
| BgChanged String
| BhChanged String
init : () -> Url.Url -> Nav.Key -> ( Model, Cmd Msg )
init flag url key =
( Model key url (A "" "" "" "") (B "" "" "" ""), Cmd.none )
subscriptions : Model -> Sub Msg
subscriptions _ =
Sub.none
view : Model -> Document msg
view model =
{ title = "Mister Mandarin"
, body =
div
[ input [ onInput AaChanged ] []
, input [ onInput AbChanged ] []
, input [ onInput AcChanged ] []
, input [ onInput AdChanged ] []
, input [ onInput BeChanged ] []
, input [ onInput BfChanged ] []
, input [ onInput BgChanged ] []
, input [ onInput BhChanged ] []
]
[]
}
update : Msg -> Model -> ( Model, Cmd msg )
update msg model =
case msg of
LinkClicked urlRequest ->
case urlRequest of
Browser.Internal url ->
( model, Nav.pushUrl model.key (Url.toString url) )
Browser.External href ->
( model, Nav.load href )
UrlChanged url ->
( { model | url = url }
, Cmd.none
)
AaChanged value ->
let
a =
model.a
newA =
{ a | a = value }
in
( { model | a = newA }, Cmd.none )
AbChanged value ->
let
a =
model.a
newA =
{ a | b = value }
in
( { model | a = newA }, Cmd.none )
AcChanged value ->
let
a =
model.a
newA =
{ a | c = value }
in
( { model | a = newA }, Cmd.none )
AdChanged value ->
let
a =
model.a
newA =
{ a | d = value }
in
( { model | a = newA }, Cmd.none )
BeChanged value ->
let
b =
model.b
newB =
{ b | e = value }
in
( { model | b = newB }, Cmd.none )
BfChanged value ->
let
b =
model.b
newB =
{ b | f = value }
in
( { model | b = newB }, Cmd.none )
BgChanged value ->
let
b =
model.b
newB =
{ b | g = value }
in
( { model | b = newB }, Cmd.none )
BhChanged value ->
let
b =
model.b
newB =
{ b | h = value }
in
( { model | b = newB }, Cmd.none )
main : Program () Model Msg
main =
Browser.application
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
, onUrlChange = UrlChanged
, onUrlRequest = LinkClicked
}
对于这个问题,我采用了两种截然不同的方法。给你最大的控制权(同时仍然有助于消除冗长)的方法是将你的逻辑从 Update
移动到你的 View
和一个通用的 Msg
。类似于:UpdateForm (String -> Model)
或 UpdateForm (String -> FormModel)
.
另一种方法是完全不在模型中存储输入状态。这样做的缺点是不允许您执行初始化输入或轻松清除输入等操作。但它作为一种快速而肮脏的方法来获取基本表格是很棒的。在此方法中,您利用了具有 name
属性的输入元素成为父 form
元素1 的属性这一事实。可以给表单的onSubmit
附加解码器,通过Decode.at ["ab", "value"]
.
获取值
1https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-name
elm 中是否有一种模式可以避免编写大量消息来更新模型子元素上的各个字段?
目前,我的代码如下所示,其中包含针对每个更改的输入的消息,然后是针对每个字段的一堆更新逻辑。我想要做的是有一条像 AChanged 这样的消息,它处理对 A 的任何 属性 的所有更改。通过更新生成消息的函数中的记录或通过传入字段名称然后使用它像在 Javascript.
中那样直接对记录执行更新module Main exposing (Model)
import Browser exposing (Document, UrlRequest)
import Browser.Navigation as Nav exposing (Key)
import Html exposing (div, input)
import Html.Events exposing (onInput)
import Url exposing (Url)
type alias A =
{ a : String
, b : String
, c : String
, d : String
}
type alias B =
{ e : String
, f : String
, g : String
, h : String
}
type alias Model =
{ key : Nav.Key
, url : Url.Url
, a : A
, b : B
}
type Msg
= UrlChanged Url.Url
| LinkClicked Browser.UrlRequest
| AaChanged String
| AbChanged String
| AcChanged String
| AdChanged String
| BeChanged String
| BfChanged String
| BgChanged String
| BhChanged String
init : () -> Url.Url -> Nav.Key -> ( Model, Cmd Msg )
init flag url key =
( Model key url (A "" "" "" "") (B "" "" "" ""), Cmd.none )
subscriptions : Model -> Sub Msg
subscriptions _ =
Sub.none
view : Model -> Document msg
view model =
{ title = "Mister Mandarin"
, body =
div
[ input [ onInput AaChanged ] []
, input [ onInput AbChanged ] []
, input [ onInput AcChanged ] []
, input [ onInput AdChanged ] []
, input [ onInput BeChanged ] []
, input [ onInput BfChanged ] []
, input [ onInput BgChanged ] []
, input [ onInput BhChanged ] []
]
[]
}
update : Msg -> Model -> ( Model, Cmd msg )
update msg model =
case msg of
LinkClicked urlRequest ->
case urlRequest of
Browser.Internal url ->
( model, Nav.pushUrl model.key (Url.toString url) )
Browser.External href ->
( model, Nav.load href )
UrlChanged url ->
( { model | url = url }
, Cmd.none
)
AaChanged value ->
let
a =
model.a
newA =
{ a | a = value }
in
( { model | a = newA }, Cmd.none )
AbChanged value ->
let
a =
model.a
newA =
{ a | b = value }
in
( { model | a = newA }, Cmd.none )
AcChanged value ->
let
a =
model.a
newA =
{ a | c = value }
in
( { model | a = newA }, Cmd.none )
AdChanged value ->
let
a =
model.a
newA =
{ a | d = value }
in
( { model | a = newA }, Cmd.none )
BeChanged value ->
let
b =
model.b
newB =
{ b | e = value }
in
( { model | b = newB }, Cmd.none )
BfChanged value ->
let
b =
model.b
newB =
{ b | f = value }
in
( { model | b = newB }, Cmd.none )
BgChanged value ->
let
b =
model.b
newB =
{ b | g = value }
in
( { model | b = newB }, Cmd.none )
BhChanged value ->
let
b =
model.b
newB =
{ b | h = value }
in
( { model | b = newB }, Cmd.none )
main : Program () Model Msg
main =
Browser.application
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
, onUrlChange = UrlChanged
, onUrlRequest = LinkClicked
}
对于这个问题,我采用了两种截然不同的方法。给你最大的控制权(同时仍然有助于消除冗长)的方法是将你的逻辑从 Update
移动到你的 View
和一个通用的 Msg
。类似于:UpdateForm (String -> Model)
或 UpdateForm (String -> FormModel)
.
另一种方法是完全不在模型中存储输入状态。这样做的缺点是不允许您执行初始化输入或轻松清除输入等操作。但它作为一种快速而肮脏的方法来获取基本表格是很棒的。在此方法中,您利用了具有 name
属性的输入元素成为父 form
元素1 的属性这一事实。可以给表单的onSubmit
附加解码器,通过Decode.at ["ab", "value"]
.
1https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-name