Vanilla.js Data-Binding
How to implement data-binding with plain old JavaScript
by Jeremy Likness
HTML
First name:
<input id="firstName" type="text" />
<br/> Last name:
<input id="lastName" type="text" />
<br/> Age:
<input id="age" type="number" />
<br/>
<p id="output">
Fill out the form!
</p>
<button id="reset">
Reset
</button>
JavaScript
(function() {
const inpFirstName = document.getElementById('firstName'),
inpLastName = document.getElementById('lastName'),
inpAge = document.getElementById('age'),
pOutput = document.getElementById('output'),
btnReset = document.getElementById('reset');
const onPropertyChangedFn = (callbackList, propertyName) => {
callbackList.forEach(cb => cb(propertyName));
}
const observeDOM = (elem, eventName, fn) => {
elem.addEventListener(eventName, () => fn(elem));
};
class ViewModel {
constructor() {
this.cbList = [];
this._firstName = '';
this._lastName = '';
this._age = null;
}
registerPropertyChange(cb) {
this.cbList.push(cb);
}
get firstName() {
return this._firstName;
}
set firstName(val) {
if (val !== this._firstName) {
this._firstName = val;
onPropertyChangedFn(this.cbList, 'firstName');
}
}
get lastName() {
return this._lastName;
}
set lastName(val) {
if (val !== this._lastName) {
this._lastName = val;
onPropertyChangedFn(this.cbList, 'lastName');
}
}
get age() {
return this._age;
}
set age(val) {
if (Number(val) !== this._age) {
this._age = Number(val);
onPropertyChangedFn(this.cbList, 'age');
}
}
}
var vm = new ViewModel();
observeDOM(inpFirstName, 'blur', inp => vm.firstName = inp.value);
observeDOM(inpLastName, 'blur', inp => vm.lastName = inp.value);
observeDOM(inpAge, 'keyup', inp => vm.age = inp.value);
observeDOM(btnReset, 'click', () => {
vm.firstName = '';
vm.lastName = '';
vm.age = 0;
inpFirstName.focus();
});
vm.registerPropertyChange(prop => {
if (prop === 'firstName') {
inpFirstName.value = vm.firstName;
}
if (prop === 'lastName') {
inpLastName.value = vm.lastName;
}
if (prop === 'age') {
inpAge.value = vm.age;
}
const txt = 'Hi,...