shkipper
shkipper

Reputation: 1413

Automatically add new row to table when editing last one

I'm trying to add a new row to the end of the table when user starts typing in last row. The viewmodel looks like this one:

function tableRow(number, ownerViewModel) {  
    this.number = ko.observable(number);
    this.remove = function () { ownerViewModel.tableRows.destroy(this); }

    ko.dependentObservable(function () {
        var curval = this.number();
        var rows = ownerViewModel.tableRows();
        if (rows.length > 0) {
            if (curval != '' && this == rows[rows.length - 1]) {
                ownerViewModel.addNewRow();
            }
        }
    }, this);
}

function tableRowsViewModel() {
    var that = this;
    this.tableRows = ko.observableArray([]);
    this.addNewRow = function () {
        this.tableRows.push(new tableRow('', that));
    }
    this.addNewRow();
}

$(document).ready(function () {
    ko.applyBindings(new tableRowsViewModel());
});

And here is html:

<table>
    <thead>
        <tr>
            <th>
                Number
            </th>
            <th>
            </th>
        </tr>
    </thead>
    <tbody data-bind="template:{name:'tableRow', foreach: tableRows}">
    </tbody>
    <tfoot>
        <tr>
            <td colspan="4">
                <button type="button" data-bind="click: addNewRow">
                    add row
                </button>
            </td>
        </tr>
    </tfoot>
</table>
<script id="tableRow" type="text/html">
    <tr>
        <td>
            <input type="text" style="width:40px;" data-bind="value: number, valueUpdate: 'keyup'" />
        </td>
        <td>
            <button type="button" data-bind="click: function(){ $data.remove(); }">
                delete
            </button>
        </td>
    </tr>
</script>

I've also inserted alert() in tableRow ko.dependentObservable function:

ko.dependentObservable(function () {
    alert('test');
    var curval = this.number();...

It seems like this function is fired 5 times when tableRows array contain 2 elements, 6 times when there are 3 elements in array and so on.

Am I doing this right?

Upvotes: 5

Views: 7557

Answers (1)

RP Niemeyer
RP Niemeyer

Reputation: 114792

The dependentObservable that you are adding to each row object is firing each time that a row is added, because they depend on tableRows. So, each one is doing some work to determine if they are the last row. If it is the last row, then a new row is added.

An alternative is to use a single dependentObservable that represents the last row's value. Then, you can subscribe to changes to that dependentObservable, check if it has a value, and add a row when necessary. It would look something like: http://jsfiddle.net/rniemeyer/F5F8S/

Also, here is a sample that I had from the KO forums that shows adding a row and also removing the last row if the last two are empty in case it helps: http://jsfiddle.net/rniemeyer/MzGDr/

Upvotes: 7

Related Questions