Jedediah
Jedediah

Reputation: 1944

Why would an observable array have 0 length on my template, but not in my JS in knockout.js?

I'm having some trouble with conditional rendering in knockout.js. I have an observableArray in my view model, which is created using ko.utils.arrayMap(). In my javascript code, outputting the length of that array returns the expected length. However, when I try to output that same length in my view, it's always 0.

Here is my view code:

<!-- ko if: people().length == 0 -->
    <p data-bind="text: people().length"></p>
    <!-- always outputs 0 -->
<!-- /ko -->
<!-- ko if: people().length > 0 -->
    <p data-bind="text: people().length"></p>
    <!-- never reaches this -->
<!-- /ko -->

Javascript:

var data = [
    {
        firstName: "Bob",
        lastName: "Smith"
    },
    {
        firstName: "John",
        lastName: "Doe"
    },
    {
        firstName: "Jane",
        lastName: "Doe"
    }
];

function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
}

function ViewModel(data) {
    var self = this;
    self.people = ko.observableArray(ko.utils.arrayMap(data, function(i) {
        return ko.observable(new Person(i.firstName, i.lastName));
    }));
    console.log(self.people().length);  //Outputs 3, as expected
}

ko.applyBindings(new ViewModel(data));

Upvotes: 1

Views: 208

Answers (1)

Michael Best
Michael Best

Reputation: 16688

This can happen if you replace an observable in the view model instead of assigning to it. You might have self.people = ko.observableArray(); in your view model constructor. Later, when you actually get the data, you have self.people = ko.observableArray(thedata);.

In this case, your view model knows about the data, but the view was bound to the earlier observable and doesn't know about the later one. Instead you should have self.people(thedata); to set the data.

Upvotes: 3

Related Questions