create element builder without react
from time to time for small demos need something light to create elements
unfortunately native api does not have chaining so lets build our own
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>createElement</title>
</head>
<body>
<div id="root"></div>
<script>
HTMLElement.prototype.withAttribute = function (qualifiedName, value) {
if (typeof value === 'string') {
this.setAttribute(qualifiedName, value)
} else {
this[qualifiedName] = value
}
return this
}
HTMLElement.prototype.withAttributes = function (props) {
for (const [key, value] of Object.entries(props)) {
this.withAttribute(key, value)
}
return this
}
HTMLElement.prototype.withChild = function () {
for(const child of arguments) {
if (Array.isArray(child)) {
for(const item of child) {
this.append(item)
}
} else {
this.append(child)
}
}
return this
}
HTMLElement.prototype.withStyle = function (style, value) {
this.style[style] = value
return this
}
HTMLElement.prototype.withStyles = function (styles) {
for (const [key, value] of Object.entries(styles)) {
this.withStyle(key, value)
}
return this
}
HTMLElement.prototype.clear = function () {
while (this.firstChild) {
this.removeChild(this.lastChild);
}
return this
}
</script>
<script>
const items = [
{id: 1, title: 'Buy the milk', done: false, age: 2},
{id: 2, title: 'Render items', done: true, age: 42},
]
function handleFormSubmit(event) {
event.preventDefault()
console.log('submit', event)
}
document.getElementById('root').append(
document.createElement('H3').withChild('Hello World'),
document.createElement('form').withAttribute('onsubmit', handleFormSubmit).withChild(
document.createElement('input').withAttribute('name', 'name').withAttribute('required', true),
),
document.createElement('OL').withChild(
items.map(p => document.createElement('LI').withChild(
document.createElement('input').withAttributes({type: 'checkbox', value: p.id, id: `item-${p.id}`}).withAttribute('onchange', e => { items.find(t => t.id == e.target.value).done = !items.find(t => t.id == e.target.value).done }),
document.createElement('label').withAttribute('for', `item-${p.id}`).withChild(
document.createElement(p.done ? 's' : 'span').withStyle('color', p.done ? 'gray' : 'inherit').withChild(p.title),
` (${p.age})`
)
))
)
)
</script>
</body>
</html>