Renderer ✨
Provides a single-page application (SPA) renderer with reactivity features. It likely contains functions or classes that allow developers to dynamically update the content of a web page without reloading the entire page.
Moving Between Routes 🎈
To move to other location just use route("/path")
Usage 🔨
import happyx appRoutes("app"): "/": tDiv: "Hello, world!"
Types
App = ref object appId*: cstring router*: proc (force: bool = false)
AppEventHandler = proc (ev: JsonNode = newJObject()): void
BaseComponentObj {.inheritable.} = object uniqCompId*: string isCreated*: bool slot*: proc (scopeSelf: BaseComponent; inComponent: bool; compName: string; inCycle: bool; cycleCounter: var int; compCounter: string): TagRef slotData*: TagRef created*: ComponentEventHandler ## Calls before first rendering exited*: ComponentEventHandler ## Calls after last rendering rendered*: ComponentEventHandler ## Calls after every rendering pageHide*: ComponentEventHandler ## Calls after every rendering pageShow*: ComponentEventHandler ## Calls after every rendering beforeUpdated*: ComponentEventHandler ## Calls before every rendering updated*: ComponentEventHandler ## Calls after every DOM rendering
ComponentEventHandler = proc (self: BaseComponent; ev: JsonNode = newJObject()): void
Vars
application: App = nil
- global application variable
componentEventHandlers = newTable(32)
components = newTable(32)
componentsResult = newTable(32)
createdComponentsList: seq[BaseComponent] = @[]
currentComponent = ""
- Current component unique ID
currentComponentsList: seq[BaseComponent] = @[]
currentRoute: cstring = "/"
- Current route path
eventHandlers = newTable(32)
rendererHandlers = newSeq(Natural(0))
requestResult = newTable(32)
Procs
proc html(comp: BaseComponent; data: string) {.inline, ...raises: [], tags: [], forbids: [].}
proc html(host, data: string) {.inline, ...raises: [], tags: [], forbids: [].}
proc injectJs(host, script: string) {.inline, ...raises: [ValueError], tags: [], forbids: [].}
proc js(comp: BaseComponent; script: string) {.inline, ...raises: [ValueError], tags: [], forbids: [].}
proc registerApp(appId: cstring = "app"): App {.discardable, inline, ...raises: [], tags: [], forbids: [].}
-
Creates a new Single Page Application
âš This is Low-level API âš
use appRoutes proc instead of this because this procedure calls automatically.
proc registerComponent(name: string; component: BaseComponent): BaseComponent {. inline, ...raises: [KeyError], tags: [], forbids: [].}
-
Register a new component.
âš This is Low-level API âš
Don't use it because it used in component macro.
proc renderVdom(app: App; tag: TagRef; force: bool = false) {.inline, ...raises: [], tags: [], forbids: [].}
- Rerender DOM with VDOM
proc route(comp: BaseComponent; path: string) {.inline, ...raises: [], tags: [], forbids: [].}
proc route(host, path: string) {.inline, ...raises: [], tags: [], forbids: [].}
Methods
method render(self: BaseComponent): TagRef {.base, inline, ...raises: [], tags: [], forbids: [].}
- Basic method that needs to overload in components
method reRender(self: BaseComponent) {.base, inline, ...raises: [], tags: [], forbids: [].}
- Basic method that needs to overload in components
Macros
macro appRoutes(name: string; body: untyped): untyped
-
Registers a new Single page application, creates routing for it and starts SPA.
High-level API
Use it to write your application.
Automatically creates app variable
Basic Usage:
appRoutes("app"): "/": "Hello, world!"
macro buildComponentHtml(componentName, html: untyped): untyped
-
buildHtml macro provides building HTML tags with YAML-like syntax. This macro doesn't generate Root tag
Args:
- html: YAML-like structure.
macro buildHtml(html: untyped): untyped
-
buildHtml macro provides building HTML tags with YAML-like syntax. This macro doesn't generate Root tag
Args:
- html: YAML-like structure.
macro buildHtml(root, html: untyped): untyped
-
buildHtml macro provides building HTML tags with YAML-like syntax.
Args:
- root: root element. It's can be tag, tag or tTag
- html: YAML-like structure.
Syntax support:
- attributes via exprEqExpr
echo buildHtml(`div`): h1(class="myClass", align="center") input(`type`="password", align="center")
- nested tags
echo buildHtml(`div`): tag: tag1: tag2: tag1withattrs(attr="value")
- if-elif-else expressions
var state = true state2 = true echo buildHtml(`div`): if state: "True!" else: "False(" if state2: "State2 is true"
- case-of statement:
type X = enum: xA, xB, xC var x = xA echo buildHtml(`div`): case x: of xA: "xA" of xB: "xB" else: "Other
- for statement
var state = @["h1", "h2", "input"] echo buildHtml(`div`): for i in state: i
- while statement
var state = 0 echo buildHtml(`div`): while state < 10: nim: inc state "{state}th"
- rawHtml statement
echo buildHtml(`div`): rawHtml: """ <div> Hello, world! </div> """
- script statement
echo buildHtml(`div`): tScript(...): """ console.log("Hello, world!"); """
- component usage
component MyComponent component MyComponent(field1 = value1, field2 = value2) component MyComponent: slotHtml
macro buildHtmlSlot(html: untyped; inCycle, inComponent: static[bool]): untyped
-
buildHtml macro provides building HTML tags with YAML-like syntax. This macro doesn't generate Root tag
Args:
- html: YAML-like structure.
macro elem(name: untyped): untyped
-
elem macro is just shortcut for
block: var res: Element {.emit: "`res` = document.getElementById('name')".} res
âš Works only on JS backend âš
Templates
template start(app: App)
-
Starts single page application
âš This is Low-level API âš
use appRoutes proc instead of this because this procedure calls automatically.
Exports
-
initTag, tag, textTag, addArgIter, initTag, TagRef, tag, toSeqIter, findByTag, []=, $, add, initTag, get, getAttribute, lvl, UnclosedTags, NimKeywords, initTag, tagFromString, [], addArg, []