Elm: Conditional Warning Default (with contentEditable)

I am trying to create a tag for editing content that uses enter to update the model.

My code is below and here is the version with which you can play with Ellie .

The blur attribute works and updates the model when clicked. But I want the same โ€œupgradeโ€ functionality when the enter button is pressed.

view : Model -> Html Msg view model = let attrs = [ contenteditable True --, on "blur" (Json.map UpdateTitle targetTextContent) , onInput2 UpdateTitle , onEnter EnterPressed , id "title" , class "title" ] in div [] [ h1 attrs [ text model.existing ] , text "Click above to start editing. Blur to save the value. The aim is to capture an <enter> and interpret that as a blur, ie to save the value and blur the field" , p [] [ text <| "(" ++ model.existing ++ ")" ] ] targetTextContent : Json.Decoder String targetTextContent = Json.at [ "target", "textContent" ] Json.string onInput2 : (String -> msg) -> Attribute msg onInput2 msgCreator = on "input" (Json.map msgCreator targetTextContent) onEnter : (Bool -> msg) -> Attribute msg onEnter enterMsg = onWithOptions "keydown" { stopPropagation = False , preventDefault = False } (keyCode |> Json.andThen (\ch -> let _ = Debug.log "on Enter" ch in Json.succeed (enterMsg <| ch == 13) ) ) 

This code seems to update the model in order, but the DOM gets confused. For example, if I type enter after the "explosion", I see this

enter image description here

I tried switching to Html.Keyed and using "keydown", but that didn't make any difference or just created various problems.

+5
source share
1 answer

Solved! The key point is the filter function, which uses Json.Decode.fail, so that only <enter> is subject to Default prevention. For this idea see https://github.com/elm-lang/virtual-dom/issues/18#issuecomment-273403774 .

 view : Model -> Html Msg view model = let attrs = [ contenteditable True , on "blur" (Json.map UpdateTitle targetTextContent) , onEnter EnterPressed , id "title" , class "title" ] in div [] [ h1 attrs [ text model.existing ] , text "Click above to start editing. Blur to save the value. The aim is to capture an <enter> and interpret that as a blur, ie to save the value and blur the field" , p [] [ text <| "(" ++ model.existing ++ ")" ] ] targetTextContent : Json.Decoder String targetTextContent = Json.at [ "target", "textContent" ] Json.string onEnter : msg -> Attribute msg onEnter msg = let options = { defaultOptions | preventDefault = True } filterKey code = if code == 13 then Json.succeed msg else Json.fail "ignored input" decoder = Html.Events.keyCode |> Json.andThen filterKey in onWithOptions "keydown" options decoder 
+6
source

Source: https://habr.com/ru/post/1264564/


All Articles