Reputation: 349
I finished loading resources from an API in Elm, everything is fine... except for one litte problem : I don't know how to update or create a new record without persisting it.
I have a type Msg (I striped some code for this demo)
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" ]
]
I would love to be able to add a new model from this form (formCreateUser), but I keep getting this error :
The 3rd element has this type:
VirtualDom.Node Msg
But the 4th is:
Html Link -> Html (String -> Msg)
edit2: Add some context
Upvotes: 0
Views: 787
Reputation: 36375
If I understand your example snippets, you have a page that shows the list of existing user, and you want to have a "quick add" form that lets you create another user given only a title. I'll give a quick example of how to achieve this which should hopefully shed some light on the problems you've run into.
I'm assuming your User and Model look like this at present:
type alias Model =
{ users : List User
, isLoading : Bool
}
type alias User =
{ title : String
, username : String
, email : String
}
Since you have that quick add form, I don't think you want to append the new user until they hit Submit. With that notion in mind, let's update Model to store the pending new user title:
type alias Model =
{ users : List User
, isLoading : Bool
, newUserTitle : Maybe String
}
Now we can change your view function accordingly. Since we want to display the typed title in the textbox, let's change formCreateUser
to this:
formCreateUser model =
div []
[ input [ onInput UpdateTitle, placeholder "Title", value (Maybe.withDefault "" model.newUserTitle) ] []
, button [ onClick SaveUser ] [ text "Save" ]
]
That means the calling code in view
needs updating too:
view model =
div []
[ div [] (List.map displayRow model.users)
, formCreateUser model
]
Now we need to handle the UpdateTitle
Msg to set the contents as they are typed:
UpdateTitle newTitle ->
( { model | newUserTitle = Just newTitle }, Cmd.none )
And now we can also handle the submit button. This is where you would create the new user and append it to the list of existing users:
SaveUser ->
case model.newUserTitle of
Nothing -> (model, Cmd.none)
Just title ->
( { model
| newUserTitle = Nothing
, users = model.users ++ [{ title = title, username = "", email = "" }]
}, Cmd.none)
If you wanted SaveUser
to submit it to your API endpoint, you'd also return an appropriate Cmd
, but that seems outside the scope of your question.
While this all isn't an ideal way to handle your situation, hopefully this explanation gives you more understanding of the building blocks needed for this type of thing. I've posted the full gist here which can be pasted and run in elm-lang.org/try.
Upvotes: 2