Inspired by a tweet from a fellow developer, I decided to take a look at Karax, a nifty framework for developing single page applications in Nim.
After following the basic tutorials and examples, I searched for something more complex and found very sparse documentation, so I’ll write my findings here.
As usual, the complete source code is on my github repo, where you can find also a working live demo.
In this example I wanted to experiment with the component pattern, and create a stateful module that can be reused. So I modeled a nim clock object, here the source:
# source for the Clock component
import karax/[karax, karaxdsl, vdom]
import std/times
import std/dom
import sugar
type
KClock* = ref object of VComponent
currentTime: DateTime
offset: TimeInterval
timer: TimeOut
prefix: string
# return a VNode with the html rendered for the component
proc render(c: VComponent): VNode =
let self = KClock(c)
buildHtml(tdiv):
let value = format(self.currentTime+self.offset, "HH:mm:ss")
p:
text "Local Time " & self.prefix & " => " & value
# update the clock value and re-triggers a timer
proc update(self: KClock) =
self.currentTime = now()
self.timer = setTimeout( () => self.update, 100)
markDirty(self) # need to be re-rendered
redraw()
# create, initialize and return a new Clock object
proc new*(T: type KClock, tzoffset = 0): KClock =
let self = newComponent(KClock, render)
self.currentTime = now()
self.offset = initTimeInterval(hours = tzoffset)
self.timer = setTimeout(() => self.update, 100)
self.prefix = if tzoffset >= 0: "+" else: ""
self.prefix.add $tzoffset
return self
this lives in a separate file and can be imported from the main page.
Some attention point goes in the constructor, that requires special newComponent
call, and the update()
function that contains a Timeout callback in order to re-render itself after some time.
let’s use the component in the main page, and sprinkle some interactivity just for fun:
import karax / [kbase, vdom, kdom, karax, karaxdsl, jstrutils]
import kclock
var
clocks: seq[KClock] # keep a list of clocks
offset: kstring # value entered in the input box
proc render(): VNode =
buildHtml(tdiv):
h2:
label(`for` = "offset"):
text "Please enter Timezone offset (-12 .. +12)"
input(type = "number", id = "offset"):
proc oninput(ev: Event; n: VNode) =
offset = n.value
button:
text "Add a new Clock"
proc onclick(ev: Event; n: VNode) =
let tzofs = parseInt(offset)
if tzofs >= -12 and tzofs <= 12:
clocks.add(KClock.new(tzofs))
button:
text "Remove last Clock"
proc onclick(ev: Event; n: VNode) =
discard clocks.pop()
for clock in clocks:
h1:
clock
setRenderer render
for Nim lovers, Karax looks promising, and programming web pages without writing a single Javascript line sounds very interesting; but currently it needs some polish, more documentation and a larger user base. So try and contribute to the development community!