Frage

I am trying to create an editable grid with a computed observableArray in MVC 4 and Knockout.js. The computed() method gets called when the array is first loaded but not when any data changes on the grid via user editing.

The ViewModel:

function CarsVm() {
var self = this;

self.url = 'http://localhost/FederatedWcf/Services/RestCars.svc/json/cars';

self.cars = ko.observableArray([]);

self.car = ko.computed(function () {
    if ( this.cars().length > 0)
        return this.cars()[this.cars().length-1].Make;
    else {
        return "";
    }
}, this);

self.GetCars = function () {
    var count = 0;
    $.getJSON(self.url, function (allData) {
        var mappedCars = $.map(allData.JsonCarsResult, function (item) {
            console.log(count);
            console.log(item);
            count = count + 1;
            return new Cars(item);
        });
        self.cars(mappedCars);
        console.log(self.cars());
    });
    $.ajaxSetup({ cache: false });
};

}

And the html fragment:

<table>
<thead>
    <tr>
        <th></th>
        <th>Year</th>
        <th>Make</th>
        <th>Model</th>
        <th></th>
    </tr>
</thead>
<tbody data-bind="foreach: cars">
    <tr>
        <td><span style="display:none" data-bind="text:Id"></span></td>
        <td><input data-bind="value:Year"></input></td>
        <td><input data-bind="value:Make"></input></td>
        <td><input data-bind="value:Model"></input></td>
        <td><button data-bind="click: $root.removeCar">-</button></td>
    </tr>
</tbody>
</table>
<span data-bind="text:car"></span>

If I edit the last Make in the grid, I expected the data bound car element to be updated but it is not.

How do I detect changes on a grid, like during an onblur event, in a knockout observerableArray?

War es hilfreich?

Lösung

Make sure to mark each property in Cars as observable or knockout won't notice they changed.

function Cars(data) {
   var self = this;
   self.Id = data.Id;
   self.Year = ko.observable(data.Year);
   self.Make = ko.observable(data.Make);
   self.Model = ko.observable(data.Model);
}

Andere Tipps

It's because when you change properties of the objects in cars, the observableArray does not observe anything (it still contains the same objects, right?)

To make it aware of the properties, you have to make each item in the observableArray an observable itself. You can do that with knockouts own mapping plugin or manually with ko.observable() in your current mapping function.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top