抱歉标题不够准确,无法确定问题所在。
我正在尝试使用Alex Lew在这篇极好的博客文章中提到的“翻译器模式”:Elm中子组件向父组件通信的模型。
但由于我是完全的Elm新手,在以下情况下并不理解:
我有一个像这样的模块(在该模式中为子组件):
module Pages.SignUp.Update exposing (update, Msg(..))
import Http
import HttpBuilder exposing (withHeader, withJsonBody, stringReader, jsonReader, send)
import Task exposing (Task)
import Json.Decode exposing (Decoder, bool, (:=))
import Json.Encode exposing (encode, object, string)
import String
import Update.Extra exposing (andThen)
import Debug
type alias Model =
{ displayName : String
, displayNameErrors : List (Maybe String)
, email : String
, emailErrors : List (Maybe String)
, password : String
, passwordConfirmation : String
, passwordErrors : List (Maybe String)
, modelValid : Bool
, emailValidationPending : Bool
, registrationPending : Bool }
emptyModel : Model
emptyModel =
{ displayName = ""
, displayNameErrors = []
, email = ""
, emailErrors = []
, password = ""
, passwordConfirmation = ""
, passwordErrors = []
, modelValid = False
, emailValidationPending = False
, registrationPending = False }
type InternalMsg
= SetEmail String
| SetDisplayName String
| SetPassword String
| SetPasswordConfirm String
| Register
| RegisterSucceed (HttpBuilder.Response Bool)
| RegisterFail (HttpBuilder.Error String)
| ValidateModel
| Noop
type OutMsg
= UserRegistered
type Msg
= ForSelf InternalMsg
| ForParent OutMsg
type alias TranslationDictionary msg =
{ onInternalMessage: InternalMsg -> msg
, onUserRegistered: msg
}
type alias Translator msg =
Msg -> msg
translator : TranslationDictionary msg -> Translator msg
translator { onInternalMessage, onUserRegistered } msg =
case msg of
ForSelf internal ->
onInternalMessage internal
ForParent UserRegistered ->
onUserRegistered
never : Never -> a
never n =
never n
generateParentMessage : OutMsg -> Cmd Msg
generateParentMessage outMsg =
Task.perform never ForParent (Task.succeed outMsg )
init : ( Model, List Notification )
init =
( emptyModel, [] )
update : InternalMsg -> Model -> (Model, Cmd Msg)
update msg model =
case Debug.log "Signup action" msg of
SetEmail emailStr ->
let model' =
{model | email = emailStr }
in
update ValidateModel model'
SetDisplayName nameStr ->
let model' =
{ model | displayName = nameStr }
in
update ValidateModel model'
SetPassword passwordStr ->
let model' =
{ model | password = passwordStr }
in
update ValidateModel model'
SetPasswordConfirm passwordConfirmStr ->
let model' =
{ model | passwordConfirmation = passwordConfirmStr }
in
update ValidateModel model'
ValidateModel ->
let validatedModel =
validateModel model
test = Debug.log "validated model" validatedModel
in
( validatedModel, Cmd.none )
Register ->
( { model | registrationPending = True }, registerUser model)
RegisterSucceed _ ->
( { model | registrationPending = False }, (generateParentMessage UserRegistered) )
RegisterFail error ->
case error of
HttpBuilder.BadResponse response ->
case Debug.log "Register response status" response.status of
422 ->
( { model | registrationPending = False }, Cmd.none )
_ ->
( { model | registrationPending = False }, Cmd.none )
_ ->
( { model | registrationPending = False }, Cmd.none)
Noop ->
(model, Cmd.none)
registerUser : Model -> Cmd Msg
registerUser model =
let url =
"/api/users"
user =
object [
("user",
object
[
("display_name", (string model.displayName)),
("email", (string model.email)),
("password", (string model.password)),
("passwordConfirmation", (string model.passwordConfirmation))
]
)
]
postRequest =
HttpBuilder.post url
|> withHeader "Content-type" "application/json"
|> withJsonBody user
|> send (jsonReader decodeRegisterResponse) stringReader
in
Task.perform ForSelf RegisterFail ForSelf RegisterSucceed postRequest
decodeRegisterResponse : Decoder Bool
decodeRegisterResponse =
"ok" := bool
validateRequired : String -> String -> Maybe String
validateRequired fieldContent fieldName =
case String.isEmpty fieldContent of
True -> Just <| String.join " " [ fieldName, "required" ]
False -> Nothing
validateEmail : String -> List (Maybe String)
validateEmail email =
let requiredResult =
validateRequired email "Email"
in
[requiredResult]
validatePassword : String -> String -> List (Maybe String)
validatePassword password passwordConf =
let requiredResult =
validateRequired password "Password"
confirmResult =
case password == passwordConf of
True -> Nothing
False -> Just "Password confirmation does not match"
in
[ requiredResult, confirmResult ]
validateModel : Model -> Model
validateModel model =
let emailResult =
validateEmail model.email
displayNameResult =
validateRequired model.displayName "Displayname" :: []
passwordResult =
validatePassword model.password model.passwordConfirmation
errors =
List.concat [emailResult, displayNameResult, passwordResult ] |> List.filterMap identity
modelValid = List.isEmpty errors
in
{ model |
emailErrors = emailResult,
displayNameErrors = displayNameResult,
passwordErrors = passwordResult,
modelValid = modelValid
}
问题出在registerUser函数上,目前它显然不能正常工作。我无法使其返回Cmd Msg。我可以使它返回Cmd InternalMsg,但是这样会导致在update函数中的Register消息出现问题。在那里,我需要将Cmd InternalMsg转换为Cmd Msg。
我尝试在两个位置都解决了这个问题,但总是失败。这很可能有一个简单的解决方案,但似乎没有技能来实现它。
非常感谢您的任何帮助。
Cmd.map ForSelf : Cmd InternalMsg -> Cmd Msg
? - Lynn