2013-03-09 3 views
18

Wie implementieren Sie eine einfache Zwei-Wege-Datenbindung in jQuery? Etwas wie KO, aber in der einfachsten möglichen Form.jQuery TwoWay-Datenbindung

Szenario - JSON-Objekt an Tabellenzeile binden (jedes Feld ist td> Eingabe />/td>).

Irgendwelche Vorschläge?

+2

Sie sollten ein konkreteres Beispiel und einige Versuche geben. – soyuka

+1

tat ich. Überprüfe meine eigene Antwort. Irgendwelche Vorschläge, Tricks? – kayz1

+0

http://jquerymy.com/ –

Antwort

11

Mein Versuch - 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

Ich habe erstaunliche Watch.JS verwendet. How Does Watch.js Work?

Watch.js now uses Object.observe

Hier ist ein weiteres Beispiel Easy Two-Way Data Binding in JavaScript.

Und ein anderer question.

Native JavaScript Data-Binding.

+2

Watch.JS sieht gut aus, aber es verwendet setInterval für regelmäßige Überprüfungen. Das kann nicht gut für die Leistung sein ... –

+2

Jetzt verwendet es object.observe, wenn vorhanden. – kayz1

+0

Super! Ich freue mich darauf, Watch.js vor dem Hintergrund dieser neuen Funktion zu testen! –

2

Diese Lösung ist ziemlich einfach, und es kann erweitert werden, um eine komplexere Funktionalität haben: http://cssshowcase.co.uk/two-way-data-binding-with-jquery/

Es buchstäblich 2 oder mehrere HTML-Elemente miteinander verbindet, mit seiner derzeitigen Form es die innere html irgendeines Elements ändert und der Wert jeder Eingabe für jedes Element, das den gleichen Attributwert "bind" enthält.