In fact, it is maybe not even too far away:
include karaxprelude
import jstrutils, dom, future
type
Model = ref object
toggle: bool
EventHandler = (Event, VNode) -> void
EventHandlerModel = (Model, Event, VNode) -> void
proc curry(handler: EventHandlerModel, model: Model): EventHandler =
result = (ev: Event, n: VNode) => handler(model, ev, n)
proc onClick(model: Model, ev: Event, n: VNode) =
kout(ev)
kout(model)
model.toggle = model.toggle xor true
proc view(model: Model): VNode =
result = buildHtml():
tdiv:
button(onclick=curry(onClick, model)):
text "click me"
tdiv:
text "Toggle state:"
tdiv:
if model.toggle:
text "true"
else:
text "false"
proc runMain() =
var model = Model(toggle: true)
proc renderer(): VNode =
# var model = Model(toggle: true) # init here does not work
view(model)
setRenderer renderer
runMain()
At first I was initializing the `model` in the renderer proc. This had the
result that the view never updated -- it's not immediately clear to me why it
has to be in the outer scope.
Adding an Elm-like message approach should also be possible by constructing
some `Msg` in each event handler and calling an `update` function. Okay, in
contrast to Elm the model is updated in-place, but maybe it is even beneficial
to keep the model update close to how it works natively.
The only issue is that every event handler has to be curried. So my question
probably becomes: Is it possible to automatize this "injection" of the model
into the event handlers, so that an event handler `(Model, Event, VNode) ->
void` can be passed directly to `on...`.