I'm using karax to write a SPA. I'm using routes as mentioned in the readme.
There is a signin form which gets a token from the backend api. Then the app has to display list of sites for that token
proc createDom(data: RouterData): VNode =
let uri = $data.hashPart
# it could be accessed / or #/
if uri.len == 0 or uri == "#/":
if state.token.len > 2: objectToShow = siteobj else: objectToShow = signinobj
elif uri.len > 2 and uri[0 .. 7] == "#/sites/": objectToShow = sitesobj
elif uri == "#/entries/": objectToShow = entryobj
result = buildHtml(tdiv(class="todomvc-wrapper")):
section(class = "todoapp"):
if uri.len > 8: state.siteId = uri[8 .. ^1]
case objectToShow:
of signinobj: signinForm()
of sitesobj: sites()
else: entry()
setRenderer createDom
In the signin form, I have this:
tdiv(class="mt3"):
button(`type`="submit"):
text "Sign-In"
proc onclick(ev: Event; n: VNode) =
ajaxPost("/api/v1/signin/",@[],$( %* {"email": $email, "password": $password}), (s:int, r: kstring)=>onPost(s,r))
ev.preventDefault()
So far so good.
Now I need to pull sites. I tried having it like this:
proc initSites() =
<pull sites here>
proc sites*():VNode =
initSites()
buildHtml(tdiv):
h1(id="title", class="tc ph4"): text "Olai - Static Blogging Tool"
header(class="tc mt4"):
h2(class="f6 gray fw2 ttu tracked"): text "Sites" & state.siteId
This gets called repeatedly (which I suppose render funcition is called repeatedly). Need help in coding this piece. How to pull data from backend to initialise a page?
Top level function calls run once, whereas each function called from the renderer will be called multiple times. So I put any single calls at the end. The redrawSync ensures that the DOM elements have been created so the data that comes back has a place to be rendered.
setRenderer createDom
redrawSync()
kajax.ajaxGet( ... )
while this works if I have only one object, it doesn't serve the purpose if I have multiple objects in different files - says sites in sites.nim, entries in entries.nim and so on. If I have these global ajaxGet in each of these files, they are all called at the start of the program which is undesirable. Also when user clicks on a different site, I want to fetch and display details of that site.
In react & vue there are lifecycle events with init which is called when the component is created. Is there something similar in Karax?
If not, how can this be done - fetching info for each object at the time of display.
Well you can use a little logic like
var loaded: bool
proc stuff*(): VNode =
if not loaded:
ajaxGet(...)
loaded = true