DEV Community

Cover image for Our first 'Hello World' with VanJS, the new Mithril...
artydev
artydev

Posted on • Edited on

Our first 'Hello World' with VanJS, the new Mithril...

Every UI framerwork deserves its 'counter' example...

SimpleCounter

import van from "https://vanjs.org/code/van-0.11.9.min.js" const {button, div, h1} = van.tags const points = van.state(0) const inc = () => ++points.val function App () { return div ( h1("Value : ", points), button({onclick : inc}, "INC") ) } van.add(app, App()) 
Enter fullscreen mode Exit fullscreen mode

In the following example, the state is represented by an object instead of a single value, read the doc for more informations.
Beware the 'actions' object is my own 'business' and has nothing to do with VanJS.

IncDec

import van from "https://vanjs.org/code/van-0.11.9.min.js" const {button, div, h1} = van.tags const State = van.state({ value : 0 }) const actions = ((state) => { const s = state.val; return ({ inc : () => { state.val = {...s, value : ++s.value} }, dec : () => { state.val = {...s, value : --s.value} } }) })(State) function App (state) { return div ( van.bind(state, (s) => h1("Value : ", s.value)), button({onclick : actions.inc}, "INC"), button({onclick : actions.dec}, "DEC") ) } van.add(app, App(State)) 
Enter fullscreen mode Exit fullscreen mode

And for the final : multiple counters :

MultipleCounters

 import van from "https://vanjs.org/code/van-0.11.9.min.js" const {button, div, h1} = van.tags // I could have use an array of values... // But I wanted to play with dynamic properties const State = van.state({ value0 : 0, value1 : 0, value2 : 0 }) const actions = ((state) => { const s = state.val; return ({ inc : (index) => { state.val = {...s, [`value${index}`] : ++s[`value${index}`]} }, dec : (index) => { state.val = {...s, [`value${index}`] : --s[`value${index}`]} } }) })(State) function Counter(state, index = 0) { return div ( van.bind(state, (s) => h1("Value : ", s[`value${index}`])), button({onclick : () => actions.inc(index)}, "INC"), button({onclick : () => actions.dec(index)}, "DEC") ) } function App (state) { return div( [...Array(3)].map((_, index) => Counter(state, index)) ) } van.add(app, App(State)) 
Enter fullscreen mode Exit fullscreen mode

Here is an optimised version, thanks Tao OpimisedMC

import van from "https://vanjs.org/code/van-0.11.9.min.js" const {button, div, h1} = van.tags const State = { value0 : van.state(0), value1 : van.state(0), value2 : van.state(0), value3 : van.state(0), } const actions = ((state) => { return ({ inc : (index) => ++(state[`value${index}`]).val , dec : (index) => --(state[`value${index}`]).val }) })(State) function Counter (state, index) { return div ( h1("Counter_", index, " : ", state[`value${index}`]), button({onclick : () => actions.inc(index)}, "INC"), button({onclick : () => actions.dec(index)}, "DEC") ) } function App (state) { return Object.keys(State) .map((_, index) => Counter(state, index) ) } van.add(app, App(State)) 
Enter fullscreen mode Exit fullscreen mode

Top comments (6)

Collapse
 
efpage profile image
Eckehard

You can also enable a sequential workflow:

 const { button, div, pre, br } = van.tags const add = (x) => van.add(base, x) let base = div({ style: "border: 2px dashed red; padding: 5px; display: inline-block;" }, "This is a group", br()) van.add(document.body, base) for (let i = 0; i < 10; i++) { add(button({ onclick: () => alert("Hello World") }, "This is button "+i)) add(br()) } 
Enter fullscreen mode Exit fullscreen mode
Collapse
 
artydev profile image
artydev • Edited

Thank you Ekehard :-)

WF

Nice , I really like your 'mix' VanJS / DML :-)

Based on your tip mAdd:

const { button, h1, div, pre, br } = van.tags const add = (base) => (elt) => van.add(base, elt) const target = document.getElementById("app") add (target) ( div ( div ( button("A button appended to #app"), button("2nd") ), div ( div(h1("Hello")) ) ) ) 
Enter fullscreen mode Exit fullscreen mode
Collapse
 
efpage profile image
Eckehard

I think it should be possible to get the best of both worlds...

Thread Thread
 
artydev profile image
artydev

Sure, I think so.
What is really amazing, it is the size.

Don't hesitate to contact Tao, the author, he is a very nice guy too...

Collapse
 
tao_xin_23db52b1401921dcb profile image
Tao Xin (vanjs.org)

btw: it would be more efficient to use multiple primitive-valued state objects compared to using a single state object that contains everything. In other words, for your example, you can have a JavaScript object that contains multiple state-valued fields, instead of having a single state object with object-typed value.

Instead of

const State = van.state({ value0 : 0, value1 : 0, value2 : 0 }) 
Enter fullscreen mode Exit fullscreen mode

you can have:

const State = { value0: van.state(0), value1: van.state(0), value2: van.state(0) } 
Enter fullscreen mode Exit fullscreen mode
Collapse
 
artydev profile image
artydev • Edited

Thank you for your advise Tao :-)

import van from "https://vanjs.org/code/van-0.11.9.min.js" const {button, div, h1} = van.tags const State = { value0 : van.state(0), value1 : van.state(0), value2 : van.state(0), value3 : van.state(0), } const actions = ((state) => { return ({ inc : (index) => ++(state[`value${index}`]).val , dec : (index) => --(state[`value${index}`]).val }) })(State) function Counter (state, index) { return div ( h1("Counter_", index, " : ", state[`value${index}`]), button({onclick : () => actions.inc(index)}, "INC"), button({onclick : () => actions.dec(index)}, "DEC") ) } function App (state) { return Object.keys(State) .map((_, index) => Counter(state, index) ) } van.add(app, App(State)) 
Enter fullscreen mode Exit fullscreen mode