Basic usage
bindDOM
Vanillin's starting point is bindDOM
. bindDOM
's signature is similar to metaesEval
. For example:
bindDOM(`<button>Click</button>`, console.log);
will pass HTMLButtonElement
element throught success callback when evaluation finishes.
Then, you can add element to the DOM:
document.body.appendChild(await uncpsp(bindDOM)(`<button>Click</button>`));
It's important to note the uncpsp
is required, not uncps
, because Vanillin by default splits work into 16ms blocks which makes synchronous result unlikely unless is trivial and fits into 16ms block.
If Vanillin runs in a web browser, DOM elements like HTMLButtonElement
are created using browser's DOMParser
. DOMParser
creates Document
with elements inside its <head>
or <body>
, but Vanillin extracts them right away and returns single element or array of elements (but not NodeList
) depending on what was provided as a string.
Existing elements
bindDOM
allows to use already existing DOM objects. For example, part of your website could look like:
<button onclick="console.log('hello world')">click</button>
Which allows you to write:
bindDOM(document.querySelector("button"), console.log, console.error);
Read more at api reference.
Rendering text using bind
Consider this example:
bindDOM(`<span bind>text</span>`, (element) => document.body.appendChild(element), console.error, {
text: "hello world"
});
bind
attribute makes Vanillin will:
- get
textContent
of currently evaluated element and treat it as JavaScript expression, - evaluate expression and set result back to
textContent
of that element.
Think of it as a template pattern, but there is no special language, there are JavaScript scripts which should evaluate to a value.
Template expressions like <span>{{value}}</span>
are not supported out of the box, but possible to implement when extending Vanillin.
Attributes binding
Attributes binding stands for setting values to elements' attributes. There are few ways you can do that. First one is:
bind-attrs
bind-attrs
is a low level tool which can be used used when list of attributes which should be bound is dynamic.
Example:
<script>
const toBind = ["href"];
</script>
<a href="someValue" bind-attrs="toBind">Click me</a>
The logic is as following:
- For each item
item
intoBind
,- read value of attribute with name equal to
item
and store it under some valuevalue
, - evaluate
value
in current environment as save its result inresult
, - set attribute's value to be
result
.
- read value of attribute with name equal to
:attr
syntax
Alternatively, you can use :href
syntax and greatly simplify the logic:
<a :href="someValue">Click me</a>
You need to do it for each attribute separately which in most of the cases should be the preferred way.
script
tag
There are several rules to remember about <script>
. <script>
:
- is evaluated in similar way to native
<script>
, but in case of Vanillin, code is evaluated with metaES. Both inline code andsrc
attribute based elements are supported.- loading of scripts configured with
src
attribute is handled by Vanillin custom loader. It can be overriten.
- loading of scripts configured with
- can additionally be configured with
observe
attibute, which will make tags body to reevaluate when any automatically observed variables changes. TODO: This could be enabled by default? - doesn't have to be added to
Document
to be evaluated, it is evaluated immediately. - doesn't create additional environment for itself:
const environment = createEnvironment();
bindDOM(
`<script>var foo='bar'</script>`,
() =>
// prints `bar` because variable `foo` was set in closest surrounding environment.
console.log(environment.foo),
console.error,
environment
);
script
attribute
script
attribute will make code contained in this attribute to be evaluated in a context where this
is bound to owning element:
bindDOM(`<textarea script="initTextarea(this)></textarea>`, console.log, console.error, {
initTextarea(element) {
// do some logic HTMLTexareaElement element
}
});
script
attribute will create additional environment:
const environment = {};
bindDOM(
`<div script="var foo='bar'"></div>`,
() =>
console.log(environment.foo); // undefined
},
console.error,
environment
);