virtual-dom icon indicating copy to clipboard operation
virtual-dom copied to clipboard

Runtime Error: replacing element with property contentEditable

Open harrysarson opened this issue 6 years ago • 1 comments

SSCCE: https://ellie-app.com/4TNwCtWm5HGa1

module Main exposing (main)

import Browser
import Html exposing (Html)
import Html.Attributes
import Html.Events
import Task
import Json.Encode


main =
    Browser.element
        { init = init
        , update = update
        , view = view
        , subscriptions = always Sub.none
        }


init : () -> ( Bool, Cmd () )
init () =
    ( False , Cmd.none )


update : () -> Bool -> ( Bool, Cmd msg )
update () _ =
    ( True, Cmd.none )


view : Bool -> Html ()
view loaded =
    case loaded of
        True ->
            Html.div [] [ Html.text "It works ok!" ]

        False ->
            Html.div
                [ (if True then
                       (Html.Attributes.property "contentEditable" (Json.Encode.bool True))
                   else
                       (Html.Attributes.attribute "contentEditable" "true")
                  )
                , Html.Events.onClick ()
                ]
                [ Html.text "CLICK ME" ]

Notes

  • Click on CLICK ME to get the runtime error.
  • Changing True to False on line 38 (i.e. setting an attribute rather than a property) fixes this.
  • Changing True to False on line 39 (i.e. the value of the contentEditable property) does *not fix this.

Discourse: https://discourse.elm-lang.org/t/why-do-i-get-a-runtime-error/3243/2

harrysarson avatar Mar 06 '19 11:03 harrysarson

Elm Virtual Dom diffing algorithm tries to remove the contentEditable property by doing:

node.contentEditable = null;

which is not supported for contentEditable.

You can produce the same error by doing in a javascript console:

document.body.contentEditable = null

This is a known bug traced here: bug #104 (specifically #81)

I guess that the work-arounds are:

  • use attribute "contenteditable" instead
  • or set the property to Encode.bool False instead of removing it from your attributes
  • or use Html.Keyed with a different identifier to force the div to be rebuilt

rlefevre avatar Mar 13 '19 09:03 rlefevre