editing in grid

https://groups.google.com/d/topic/knockoutjs/6Cfq-JjYcyM/discussion

by mcannon

HTML

<script src="http://github.com/downloads/SteveSanderson/knockout/knockout-2.1.0.js"></script>
<table class="table1" border="1" width="30%">

   <thead>

       <tr>
           <th>Identificador</th>
           <th>Nome</th>
           <th>Descricao</th>
           <th>Unidade</th>
           <th>Hora-Inicial</th>
           <th>Periodicidade</th>
           <th></th>
        </tr>
   </thead>
   <tbody data-bind=" template:{name:templateToUse, foreach:
tableItems }">
       </tbody>
</table>
     
<button data-bind="click: removeMarked">Delete Marked</button>

<script id="itemsTmpl" type="text/html">
   <tr data-bind="click: toggle, css: { marked: markedForDeletion }" >
    <td data-bind="text: identificador"></td>
    <td data-bind="text: nome"></td>
    <td data-bind="text: descricao"></td>
    <td data-bind="text: unidade"></td>
    <td data-bind="text: hora_init"></td>
    <td data-bind="text: period_cid"></td>
    <td class="buttons">
        <button data-bind="click: $root.editItem">Edit</button>
    </td>
    </tr>
</script>
     
 <script id="editTmpl" type="text/html">
   <tr>
       <td><input data-bind="value: identificador"/></td>
       <td><input data-bind="value: nome"/></td>
       <td><input data-bind="value: descricao"/></td>
       <td><input data-bind="value: unidade"/></td>
       <td><input data-bind="value: hora_init"/></td>
       <td><input data-bind="value: period_cid"/></td>
    <td class="buttons">
        <button data-bind="click: $root.acceptItemEdit">Save</button>
        <button data-bind="click: $root.cancelItemEdit">Cancel</button>
    </td>
   </tr>
   </script>

CSS

input { width: 50px; }

.marked { background: #FF8877; }

JavaScript

ko.protectedObservable = function(initialValue) {
    //private variables
    var _temp = initialValue;
    var _actual = ko.observable(initialValue);

    var result = ko.computed({
        read: _actual,
        write: function(newValue) {
            _temp = newValue;
        }
    });
    //commit the temporary value to the observale, if is different
    result.commit = function() {
        if (_temp !== _actual()) {
            _actual(_temp);
        }
    };
    //notify subscribers to update their values with the original
    result.reset = function() {
        _actual.valueHasMutated();
        _temp = _actual();
    };
    return result;
};

function TableItem(identificador, nome, descricao, unidade, hora_init, period_cid) {
    this.identificador = ko.protectedObservable(identificador);
    this.nome = ko.protectedObservable(nome);
    this.descricao = ko.protectedObservable(descricao);
    this.unidade = ko.protectedObservable(unidade);
    this.hora_init = ko.protectedObservable(hora_init);
    this.period_cid = ko.protectedObservable(period_cid);
    this.markedForDeletion = ko.observable(false);
    this.toggle = function() {
        this.markedForDeletion(!this.markedForDeletion());
    };
}

function IndicadoresViewModel() {
    var self = this;
    this.tableItems = ko.observableArray([new TableItem(1, 2, 3, 4, 5, 6), new TableItem(7, 8, 9, 10, 11, 12)]),

    this.selectedItem = ko.observable(),

    this.editItem = function(tableItem) {
        self.selectedItem(tableItem);
    };

    this.acceptItemEdit = function() {
        var item = self.selectedItem();
        for (var prop in item) {
            if (typeof item[prop].commit === "function") {
                item[prop].commit();
            }
        }
        
        self.selectedItem(null);
    }

    this.cancelItemEdit = function() {
        var item = self.selectedItem();
        for (var prop in item) {
            if (typeof item[prop].reset === "function") {
               ...