使用Elm提交表单而不跟踪字段值

时间:2017-10-05 08:02:46

标签: html-form elm

我有一个非常简单的用户名/密码登录表单。有没有办法将此表单发送到服务器并检查200s响应,而无需通过编码体操来跟踪每个字段的字符值,因为用户键入? (是的,我知道它是Elm way to do things,但是在我的模型中添加两​​个字段,两个Msg以及更新中的附带条目似乎是一个简单的登录表单的许多不需要的代码,并将密码存储在模特永远似乎是一个坏主意。)

我已阅读these two个问题,我找到了onSubmit个事件。但是,一旦update收到onSubmit事件已触发的消息,我不确定该怎么办。我觉得可能有两种方法可以前进,但我无法弄清楚如何做到:

  • 直接从表单创建POST请求并将其发送到服务器
  • 抓取两个字段的值并自行打包以发送到服务器。

我会使用默认的提交功能,但我更愿意使用异步请求登录而不是离开页面。

3 个答案:

答案 0 :(得分:2)

  

有没有办法发布这个表格而不必经过所需的编码体操   跟踪每个字符的字符值作为用户   类型?

没有。为此,需要将表单输入中的值拉出DOM。榆树阻止你这样做,所以是的,你需要光荣的体操。

  

...永远将密码存储在模型中似乎是一个坏主意。

完成密码后,您无需保留密码。有很多方法可以解决这个问题。您可以使用空String清除它,或使用Maybe String,或使用总和类型(标记)作为模型的根,而不是典型的产品类型(记录),以便您可以有效地运行时切换模型。你有选择。

  

一旦更新收到onSubmit事件已触发的消息,我不知道该怎么做。

onSubmit触发时使用Http模块构建POST请求。如果服务器将使用您需要的数据(其他状态代码)进行响应,则需要创建一个Json decoder,以便Elm可以解析数据并生成一个类型化的值(而不是一堆东西)。

此过程将生成Request,然后您需要使用Cmd Msg将其转换为Http.send这将让您有机会告诉Elm Msg在服务器响应您的请求后发送到update。此Msg的类型为Result Http.Error YourType,您可以使用Result模块中的函数进行处理。

答案 1 :(得分:2)

我遇到同样的问题here,并且在提交表单时我也发现elm很乏味,

假设这是你的观点:

import Html exposing (..)
import Html.Attributes exposing (..)
view : Model -> Html Msg
view model =
      Html.form [method "POST", action "/address"]
  [ input [ type_ "text" ,name "user"] [],
  input [ type_ "password", name "password"] [],
  input [ type_ "submit" ,value "Submit"] []
  ]

这就是我想出来的:

将提交按钮替换为:

  input [ type_ "button" 
  ,value "Submit"
  ,attribute "onclick" "javascript:this.form.submit();"] []

如果您不关心提交的返回值,显然您可以混合使用您需要的任何JavaScript。

我知道这不是" elm方式"做事,但它简单,务实,而且有效。

答案 2 :(得分:2)

虽然我会为这个案例做体操,你可以用JSON解码器做另一个体操,从DOM获取值并将它们放入一个消息中。 JSON解码器允许您使用JSON解码器从事件对象获取任何值,只要它是属性访问而不是方法调用。

另一个技巧是你可以从表单元素中按名称访问输入元素。

import Html exposing (Html)
import Html.Attributes as HA
import Html.Events as HE
import Json.Decode as Json exposing (Decoder)

type Msg
    = SubmitLogin String String

update : Msg -> Model -> Model
update msg model =
    case msg of
        SubmitLogin username password ->
            -- Do AJAX with username and password

decodeField : String -> Decoder String
decodeField name =
    Json.at
        [ "currentTarget"
        , name
        , "value"
        ]
        Json.string

decodeLoginForm : Decoder Msg
decodeLoginForm =
    Json.map2
        SubmitLogin
        (decodeField "username")
        (decodeField "password")

preventDefault : HE.Options
preventDefault =
    { preventDefault = True
    , stopPropagation = False
    }

onLoginSubmit : Html.Attribute Msg
onLoginSubmit =
    HE.onWithOptions
        "submit"
        preventDefault
        decodeLoginForm

view : Model -> Html.Html Msg
view model =
    Html.form
        [ onLoginSubmit ]
        [ Html.input
            [ HA.name "username"
            , HA.type_ "text"
            ]
            []
        , Html.input
            [ HA.name "password"
            , HA.type_ "password"
            ]
            []
        , Html.input
            [ HA.type_ "submit"
            , HA.value "Login"
            ]
            []
        ]