Reputation: 7434
How do you implement a simple two-way data binding in jQuery? Something like knockoutJS, but in the simplest possible form.
Scenario - bind JSON object to table row (every field is td>input/>/td>).
Any suggestions?
Upvotes: 28
Views: 58669
Reputation: 159
This below jQuery code working seems like two way binding in angularJs
<script purpose="Setting value for total cost">
$(document).ready(()=>{
var sumTotalCost = () => {
var val1 = +$("#base_salary").val();
var val2 = +$("#on_cost").val();
$("#total_cost").val(val1 + val2);
}
$(".sumtotal-elements").keyup(function () {
sumTotalCost()
});
})
</script>
<input class="form-control sumtotal-elements" type="text" name='base_salary'id="base_salary">
<input class="form-control sumtotal-elements" type="text" name='on_cost' id="on_cost">
<input class="form-control" type="text" name='total' id="total_cost" >
Upvotes: 0
Reputation: 4040
This solution is pretty simple, and it can be extended to have a more complex functionality: http://cssshowcase.co.uk/two-way-data-binding-with-jquery/
It literally binds 2 or more HTML elements together, with it's current form it changes the inner html of any element and the value of any input as well, for each element that holds the same "bind" attribute value.
Upvotes: 5
Reputation: 7434
My try - HTML
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Data Binding</title>
</head>
<body>
<table id="content-table">
<thead>
</thead>
<tbody></tbody>
</table>
<button id="get-data">Get</button>
<button id="set-data">Set</button>
<script src="../js/vendor/jquery-1.9.1.js"></script>
<script src="../js/vendor/jquery-migrate-1.1.1.js"></script>
<script src="../js/vendor/watch.js"></script>
<script src="../js/dataBinder.js"></script>
</body>
</html>
JavaScript
var DataBinder = (function ($) {
var _$table = null,
_objectList = [],
_fieldList = [],
_objectListLength = -1,
_fieldListLength = -1;
/* AJAX call or smth. */
var _loadData = function () {
var fakeData = [{
name: 'John',
surname: 'Doe'
}, {
name: 'Foo',
surname: 'Bar'
}];
_objectList = $.map(fakeData, function (element, index) {
var elementObject = {
_dataBinderId: index,
element: element,
input: {}
};
watch(elementObject.element, function (property, action, newValue) {
_setValue.call(elementObject, property, newValue);
});
return elementObject;
});
_objectListLength = _objectList.length;
};
var _getFields = function () {
for (var i = 0; i < _objectListLength; i++) {
for (var field in _objectList[i].element) {
if (!!!~$.inArray(field, _fieldList)) {
_fieldList.push(field);
}
}
}
_fieldListLength = _fieldList.length;
};
var _setValue = function (field, value) {
this.input[field].val(value);
};
var _bindEvents = function () {
$('#get-data').on('click', function () {
alert(JSON.stringify(_getRowData()));
});
$('#set-data').on('click', function () {
_objectList[0].element.name = 'PIPA';
_objectList[1].element.surname = 'BLAAAAAAH';
});
_$table.on('keyup', 'input', function () {
var $this = $(this), field = $this.data('field'), source = $this.closest('tr').data('source');
source[field] = $this.val();
});
};
var _getRowData = function () {
var elements = [];
$.each(_objectList, function () {
elements.push(this.element);
});
return elements;
};
var _generateEditableElements = function () {
var rowList = [], headerRow = $('<tr>');
for (var k = 0; k < _fieldListLength; k++) {
headerRow.append($('<th>', {
text: _fieldList[k].toUpperCase()
}));
}
_$table.find('thead').append(headerRow);
for (var i = 0; i < _objectListLength; i++) {
var objectData = _objectList[i], currentRow = $('<tr>');
currentRow.data('source', objectData.element);
rowList.push(currentRow);
for (var j = 0; j < _fieldListLength; j++) {
var field = _fieldList[j], $inputElement = $('<input>', {
type: 'text',
value: objectData.element[field]
});
$inputElement.data('field', field);
objectData.input[field] = $inputElement;
currentRow.append($('<td>').append($inputElement));
}
}
_$table.find('tbody').append(rowList);
};
var init = function ($table) {
_$table = $table;
_loadData();
_getFields();
_generateEditableElements();
_bindEvents();
};
return {
init: init
};
})(jQuery);
DataBinder.init($("#content-table"));
I've used amazing Watch.JS. How Does Watch.js Work?
Watch.js now uses Object.observe
Here is another example Easy Two-Way Data Binding in JavaScript.
And another question.
Native JavaScript Data-Binding.
Upvotes: 15