jQuery TwoWay Data Binding

后端 未结 2 676
长情又很酷
长情又很酷 2021-01-31 04:03

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 (eve

相关标签:
2条回答
  • 2021-01-31 04:37

    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.

    0 讨论(0)
  • 2021-01-31 04:39

    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"));
    

    Result

    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.

    0 讨论(0)
提交回复
热议问题