-
Notifications
You must be signed in to change notification settings - Fork 49
Home
bel
is a simple element creator. It returns pure DOM elements.
If you are looking for a more higher level library, that will do DOM diffing with bel
, check out https://github.com/maxogden/yo-yo.
Because bel
creates native DOM elements, they run standalone. No need to constantly update to keep in step with a framework or separate rendering library. Spend that time making each element do one thing better and better.
When compiling for production performance or when targeting older browsers, use yo-yoify to tranform your bel
or yo-yo
calls into raw document calls.
bel
uses tagged template strings to compose elements. They are part of the JavaScript language and are available in modern browsers. There are build tools to compile for older browser targets.
You can read a more detailed description on the page How bel works
// Require bel
var bel = require('bel')
// Compose an element
var element = bel`<div>Hello!</div>`
// Add to the page
document.body.appendChild(element)
With template strings, anything between the curly braces ${}
is JavaScript:
var bel = require('bel')
var bears = ['grizzly', 'polar', 'brown']
var element = bel`<ul>
${bears.map(function (bear) {
return bel`<li>${bear}</li>`
})}
</ul>`
document.body.appendChild(element)
Attributes and event handlers can be added to elements in a natural way:
var button = bel`<button class="primary" onclick=${function (e) {
alert('button was clicked!')
}}>click me</button>`
When your element has changed, call it's .update()
function to replace the element with a new one using DOM diffing:
var element = bel`<div>hello</div>`
var morphdom = require('morphdom')
// ... later ...
morphdom(element, bel`<div>changed!</div>`)
Any time the data changes, re-render your element with the new data:
function render (msg) {
return bel`<div>${msg}</div>`
}
var element = render('hello')
// ... later ...
var morphdom = require('morphdom')
morphdom(element, render('changed!'))
As your element grows more complex, simply move that portion to another function and keep passing the data down:
var bears = ['grizzly', 'polar', 'brown']
var element = render(bears)
function render (bears) {
return bel`<ul>
${bears.map(function (bear) {
return bel`<li>${button(bear)}</li>`
})}
</ul>`
}
function button (label) {
return bel`<button>${label}</button>`
}
When an event occurs and/or your data needs to change, send up an action:
var bears = ['grizzly', 'polar', 'brown']
// First render a list of bears without any selected
var element = render(bears, 'No Bear Selected')
// We pass down all the values needed to render
function render (bears, selectedBear) {
return bel`<ul>
<li><strong>${selectedBear}</strong></li>
${bears.map(function (bear) {
return bel`<li>${button(bear, selectBear)}</li>`
})}
</ul>`
}
// When a bear is selected, we update the element with the newly selected bear
function selectBear (bear) {
morphdom(element, render(bears, bear))
}
// This button doesn't need to know about the above code
// This element focuses on doing one thing, being a button
function button (label, onselected) {
return bel`<button onclick=${function () {
onselected(label)
}}>${label}</button>`
}
If an element emits many actions, you can still handle them all through a single interface:
function button (label, action) {
return bel`<button onclick=${function () {
action('clicked', label)
}} oncontextmenu=${function (e) {
e.preventDefault()
action('menu', e.target)
}}>${label}</button>`
}
var element = button('click me', function (name, item) {
console.log('do ' + name + ' action')
})
var r = 50
var svg = bel`<svg width="100" height="100" viewBox="0 0 100 100">
<circle r="${r}" cx="${r/2}" cy="${r/2}" fill="red" />
</svg>`
Be aware that SVG elements and attributes are case sensitive.
viewbox
will not be corrected toviewBox
.
Elements On npmjs.com
A primary goal of this project is to make it easy to compose and publish standalone elements to npm.
The end user doesn't even need to know they are using bel
. They can use the element like any other native element:
var breadcrumb = require('breadcrumb-element')
document.querySelector('.app').appendChild(breadcrumb([1, 2, 3]))
Or if they are using bel
, elements integrate naturally:
var bel = require('bel')
var breadcrumb = require('breadcrumb-element')
var table = require('./lib/table.js')
// Even compatible with elements not created using bel
var nonBelElement = document.createElement('h3')
nonBelElement.textContent = 'Hello!'
var app = bel`<div class="app">
${nonBelElement}
${breadcrumb([1, 2, 3])}
${table()}
</div>`