better input element handling

This commit is contained in:
Andreas Rumpf 2017-06-29 17:10:29 +02:00
commit ea7eee7564
2 changed files with 48 additions and 8 deletions

View file

@ -54,9 +54,11 @@ template nativeValue(ev): cstring = cast[Element](ev.target).value
template setNativeValue(ev, val) = cast[Element](ev.target).value = val template setNativeValue(ev, val) = cast[Element](ev.target).value = val
template keyeventBody() = template keyeventBody() =
n.value = nativeValue(ev) let v = nativeValue(ev)
n.value = v
action(ev, n) action(ev, n)
setNativeValue(ev, n.value) if n.value != v:
setNativeValue(ev, n.value)
# Do not call redraw() here! That is already done # Do not call redraw() here! That is already done
# by ``karax.addEventHandler``. # by ``karax.addEventHandler``.
@ -276,12 +278,13 @@ proc diff(newNode, oldNode: VNode; parent, current: Node; kxi: KaraxInstance): E
case result case result
of identical, similar: of identical, similar:
newNode.dom = oldNode.dom newNode.dom = oldNode.dom
assert oldNode.dom != nil
if result == similar: updateStyles(newNode, oldNode) if result == similar: updateStyles(newNode, oldNode)
if newNode.events.len != 0 or oldNode.events.len != 0: if newNode.events.len != 0 or oldNode.events.len != 0:
mergeEvents(newNode, oldNode, kxi) mergeEvents(newNode, oldNode, kxi)
#if newNode.kind == VNodeKind.input or newNode.kind == VNodeKind.textarea: if oldNode.kind == VNodeKind.input or oldNode.kind == VNodeKind.textarea:
# oldNode.dom.value = newNode.text if oldNode.text != newNode.text:
oldNode.text = newNode.text
oldNode.dom.value = newNode.text
let newLength = newNode.len let newLength = newNode.len
let oldLength = oldNode.len let oldLength = oldNode.len

View file

@ -3,6 +3,7 @@ import vdom, kdom, vstyles, karax, karaxdsl, jdict, jstrutils
type TextInput* = ref object of VComponent type TextInput* = ref object of VComponent
value: cstring value: cstring
isActive: bool isActive: bool
onchange: proc (value: cstring)
proc render(x: VComponent): VNode = proc render(x: VComponent): VNode =
let self = TextInput(x) let self = TextInput(x)
@ -38,15 +39,23 @@ proc render(x: VComponent): VNode =
markDirty(self) markDirty(self)
proc onchanged(ev: Event; n: VNode) = proc onchanged(ev: Event; n: VNode) =
kout cstring"onchanged", n.value if self.onchange != nil and self.value != n.value:
self.onchange n.value
self.value = n.value
result = buildHtml(tdiv(style=style)): result = buildHtml(tdiv(style=style)):
input(style=inputStyle, value=self.value, onblur=flip, onfocus=flip, onkeyup=onchanged) input(style=inputStyle, value=self.value, onblur=flip, onfocus=flip, onkeyup=onchanged)
proc newTextInput*(style: VStyle = VStyle(); value: cstring = cstring""): TextInput = proc setValue(x: TextInput; value: cstring) =
x.value = value
markDirty(x)
proc newTextInput*(style: VStyle = VStyle(); value: cstring = cstring"",
onchange: proc(v: cstring) = nil): TextInput =
result = newComponent(TextInput, render) result = newComponent(TextInput, render)
result.style = style result.style = style
result.value = value result.value = value
result.onchange = onchange
type type
Combined = ref object of VComponent Combined = ref object of VComponent
@ -76,8 +85,36 @@ proc newCombined*(style: VStyle = VStyle()): Combined =
result.a = newTextInput(style, "AAA") result.a = newTextInput(style, "AAA")
result.b = newTextInput(style, "BBB") result.b = newTextInput(style, "BBB")
var
persons: seq[cstring] = @[cstring"Karax", "Abathur", "Fenix"]
selected = -1
errmsg = cstring""
ti = newTextInput(VStyle(), "", proc (v: cstring) =
if v.len > 0:
if selected >= 0: persons[selected] = v
errmsg = ""
else:
errmsg = "name must not be empty"
)
proc renderPerson(text: cstring, index: int): VNode =
proc select(ev: Event, n: VNode) =
selected = index
ti.setValue(persons[selected])
result = buildHtml():
tdiv(onClick=select):
text text
proc createDom(): VNode = proc createDom(): VNode =
result = buildHtml(tdiv): result = buildHtml(tdiv):
newCombined() tdiv:
for index, text in persons.pairs:
renderPerson(text, index)
tdiv:
ti
tdiv:
text errmsg
setRenderer createDom setRenderer createDom