Empty content editable raises an error
Patitotective opened this issue · 1 comments
include karax/prelude
import karax/kdom
proc render(): VNode =
buildHtml(tdiv):
span(contenteditable = true):
text "hello"
setRenderer render
If you compile the code above, focus the span and empty it (by backspacing or Ctrl+A backspace/delete) you'll get the following error:
Uncaught Error: Error: unhandled exception: /home/cristobal/.nimble/pkgs/karax-1.3.0/karax/karax.nim(674, 16) `same(kxi.currentTree, document.getElementById(kxi.rootId))` [AssertionDefect]
Traceback (most recent call last)
/home/cristobal/.nimble/pkgs/karax-1.3.0/karax/karax.nim(710) at redraw.:anonymous
/home/cristobal/.nimble/pkgs/karax-1.3.0/karax/karax.nim(674) at karax.dodraw
/home/cristobal/.choosenim/toolchains/nim-1.6.12/lib/system/assertions.nim(38) at assertions.failedAssertImpl
/home/cristobal/.choosenim/toolchains/nim-1.6.12/lib/system/assertions.nim(28) at assertions.raiseAssert
/home/cristobal/.choosenim/toolchains/nim-1.6.12/lib/system/fatal.nim(54) at sysFatal.sysFatal
unhandledException file:///home/cristobal/dev/test/app.js:5440
raiseException file:///home/cristobal/dev/test/app.js:1271
sysFatal_218103842 file:///home/cristobal/dev/test/app.js:5478
raiseAssert_218103840 file:///home/cristobal/dev/test/app.js:5488
failedAssertImpl_218103864 file:///home/cristobal/dev/test/app.js:5498
dodraw_620757930 file:///home/cristobal/dev/test/app.js:7183
HEX3Aanonymous_620757989 file:///home/cristobal/dev/test/app.js:7248
app.js:5440:11
From what I figured this happens because the virtual node's value stays the same while the actual node's value is modified, so when you empty the contenteditable, the real node.childNodes
's also becomes empty, thus causing https://github.com/karaxnim/karax/blob/master/karax/karax.nim#L234 to fail.
A workaround I found was to store the real node.childNodes[0]
in a variable before the content editable empties, and when it does we use appendChild
to add it again but we change .data
to an empty string, here's a demostration:
include karax/prelude
import karax/kdom
var tempChild: Node
proc render(): VNode =
buildHtml(tdiv):
span(id = "input", contenteditable = true):
text "hello"
proc onkeydown(event: Event, node: VNode) =
let element = getElementById(node.id)
if element.childNodes.len == 1:
tempChild = element.childNodes[0]
proc oninput(event: Event, node: VNode) =
let element = getElementById(node.id)
if element.len == 0:
tempChild.data = ""
element.appendChild(tempChild)
setRenderer render
Karax version 1.3.0 - Ubuntu 22.04.2 LTS
There are probably a lot of edge cases with contentEditable. Your workaround seems reasonable but I'm not sure how we'd integrate it into Karax to avoid this. Might be worth looking into how other frameworks do it