JSFiddle - React, Tailwind, and code Playground
by Serhii Matrunchyk
HTML
<script type="text/template" id="itemTpl">
<div class="item">
<div class="name">{{name}}</div>
<div class="qty">{{qty}}</div>
<button class="btn-remove" @click="removeItem">Remove</button>
</div>
</script>
<form autocomplete="off" class="form-item">
<input id="name" />
<span>x</span>
<input type="number" min="1" id="qty" />
<button id="btn-add">Add</button>
</form>
<div id="items" class="items"/>
CSS
.items {
margin-top: 10px;
border: gray solid;
border-width: 1px 0 0 1px;
}
.item {
display: grid;
grid-template-columns: auto 50px 100px;
border: gray solid;
border-width: 0 1px 1px 0;
}
JavaScript
const addBtn = document.querySelector('#btn-add');
const itemsDiv = document.querySelector('#items');
const itemTpl = document.querySelector('#itemTpl').textContent;
const listeners = [];
const itemEvents = {
remove(i) {
console.log(i);
},
edit(i) {
console.log(i);
}
}
function grabValues() {
return {
name: document.querySelector('#name').value,
qty: document.querySelector('#qty').value,
}
}
function injectValues(data) {
// https://regex101.com/r/17Bu0k/1
return itemTpl.replace(/{{(.*?)}}/g, (i, match) => data[match]);
}
function rememberEventListeners(tpl) {
// https://regex101.com/r/8mcKYE/1
return tpl.replace(/@([\w]+?)="([\w]+?)"/g, (i, event, listener) => {
listeners.push({
id,
event,
listener,
});
return `data-action-id="${id}"`;
});
}
function compileTemplate(data) {
return rememberEventListeners(injectValues(data));
}
function renderItem(compiledTpl) {
itemsDiv.insertAdjacentHTML('beforeend', compiledTpl);
return itemsDiv.querySelector('.item:last-child');
}
function clearForm() {
document.querySelector('#name').value = '';
document.querySelector('#qty').value = '';
}
function bindEvents(el) {
listeners.forEach(({ id, event, listener }) => {
const srcEl = el.querySelector(`[data-action-id="${id}"]`);
srcEl.addEventListener(event, itemEvents[listener]);
});
}
function addItem(e) {
e.preventDefault();
const data = grabValues();
const compiledTpl = compileTemplate(data);
const itemDiv = renderItem(compiledTpl);
console.log(listeners);
bindEvents(itemDiv);
clearForm();
}
addBtn.addEventListener('click', addItem);