Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Knockout nested observableArrays appear to be undefined instead of empty. [closed]

Tags:

knockout.js

If I apply aggregate functions to nested observableArrays which are initialized with an empty array ([]), I get errors that the inner array is undefined. This only happens for the observableArray objects that are constructed with an empty array as a parameter.

This may be a bug, but perhaps/hopefully I am just missing something.

The below example works with the empty array line commented out:

also on: http://jsfiddle.net/adamtolley/4pZhR/32/

The HTML:

    <ul data-bind="template: { name: 'outerTmpl', foreach: outerArray}"></ul>
Number of inner items: <span data-bind="text: innerCount"></span>
<hr />

<div data-bind="text: ko.toJSON(viewModel)"></div>

<script id="outerTmpl" type="text/html">
    <li>
        <span data-bind="text: name"></span>
        <ul data-bind="template: { name: 'innerTmpl', foreach: innerArray}"></ul>
    </li>
</script>

<script id="innerTmpl" type="text/html">
    <li>
        <span data-bind="text: name" />
    </li>
</script>

The JS:

function outer(name, innerArray) {
    return {
        name: ko.observable(name),
        innerArray: ko.observableArray(innerArray)
    };
}

function inner(name) {
    return {
        name: ko.observable(name)
    };
}

var viewModel = {
    outerArray: ko.observableArray([
        new outer("outer1", [new inner("inner1"), new inner("inner2")]),
        new outer("outer2", [new inner("inner1"), new inner("inner2")]) //,
        // new outer("outer3", []) //does not work with this line uncommented. 
    ])
};

//use of innerArray().length vs innerArray.length seems to make no difference in error   
viewModel.innerCount = ko.dependentObservable(function() {
    return this.outerArray().reduce(function(i, j) {
        return i.innerArray.length + j.innerArray.length;
    });
}, viewModel);


ko.applyBindings(viewModel);
like image 403
Adam Tolley Avatar asked Dec 13 '25 01:12

Adam Tolley


1 Answers

I think that you would want something more like:

viewModel.innerCount = ko.dependentObservable(function() {
    return this.outerArray().reduce(function(i, j) {
        var count = i.innerArray ? i.innerArray().length : i;
        return count + j.innerArray().length;
    });
}, viewModel);

The issue is that reduce will pass the previous result in as i on the next iteration. So, you only have two arrays on the first iteration.

like image 108
RP Niemeyer Avatar answered Dec 16 '25 01:12

RP Niemeyer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!