2 way data binding in JavaScript

Viewed 18210

Two-way data binding refers to the ability to bind changes to an object’s properties to changes in the UI, and vice-versa.

Can we achieve 2-way data-binding with JavaScript?

Especially 2 Way Data Binding without Frameworks.

7 Answers

Yes, we can achieve the two way data binding using pure javascript.

twoWay=function(event) {
  var elem = document.getElementsByClassName(event.currentTarget.className);
  for(var key in elem){
    elem[key].value=event.currentTarget.value;
  }
}

You can check the jsfiddle.

Simple and working approach to two-way binding, only using vanilla JS.

<!-- index.html -->
<form action="#" onsubmit="vm.onSubmit(event, this)">
    <input onchange="vm.username=this.value" type="text" id="Username">
    <input type="submit" id="Submit">
</form>
<script src="vm.js"></script>

// vm.js - vanialla JS
let vm = {
    _username: "",
    get username() {
        return this._username;
    },
    set username(value) {
        this._username = value;
    },
    onSubmit: function (event, element) {
        console.log(this.username);
    }
}

JS Getters and Setters are quite nice for this - especially when you look at the browser support.

Adding a little elaboration to Jonas Wilms answer, here's a sample without currying and also adds event binding for a full two way bind.

// Property binding
var person = { 
  set name(v) {
    document.getElementById('name').value = v;
  },
  get name() {
    return document.getElementById('name').value;
  },
  set age(v) {
    document.getElementById('age').value = v;
  },
  get age() {
    return document.getElementById('age').value;
  }
};

// You can now set values as such
person.name = 'Cesar';
person.age = 12;

// Event binding completes the two way
function logToConsole(event) { 
  console.log(event.target.value);
}

// You can set person.name or person.age in console as well.
<label for="name">Name: </label><input id="name" onkeyup="logToConsole(event)">
<label for="age">Age: </label><input id="age" onkeyup="logToConsole(event)">

Would you mind if it would be a small component for databinding tasks that provides enough convenient databinding definition commands. I did it with databindjs. e.g.

// Lets assume that there is just simple form (target)
var simpleForm = {
   input: $('.simple .input-value'),
   output: $('.simple .output-value')
};
// And here is the simple model object (source)
var model = {
    text: 'initial value'
};

// Lets set two directional binding between [input] <-> [text]
var simpleBinding = bindTo(simpleForm, () => model, {
    'input.val': 'text',  // bind to user input
    'output.text': 'text'  // simple region that will react on user input
});
// This command will sync values from source to target (from model to view)
updateLayout(simpleBinding);
subscribeToChange(simpleBinding, () => {
    $('.simple .console').html(JSON.stringify(model));
});
// Just initialize console from default model state
$('.simple .console').html(JSON.stringify(model));

The full solution here. You can check the full implementation of the databinding core on github

Related