Search code examples
knockout.jsknockout-3.0

Sub-array within an observable array


I am trying to create a new account which contains an inner array but I get an error:

Uncaught Error: The argument passed when initializing an observable array must be an array, or null, or undefined.

Any ideas why this is not working?

<script>
    function Account(id, name, balance, deposits) {
        this.Id = id;
        this.Name = name;
        this.Balance = balance;
        this.Deposits = deposits;
    }
    var myAccountViewModel = function ()
    {
        this.Accounts = ko.observableArray([
              new Account(1, "A1", 100, [1,2]),
              new Account(2, "A2", 200, [2]),
              new Account(3, "A3", 300, [2, 3]),
              new Account(4, "A4", 400, [2,3]),
        ])
    }
    ko.applyBindings(myAccountViewModel);
</script>

HTML

<table>
    <thead>
        <tr>
            <th>S.No</th>
            <th>ID</th>
            <th>Name</th>
            <th>Balance</th>
        </tr>
    </thead>
    <tbody data-bind="foreach: {data:Accounts, as:'Account'}">
        <tr>
            <td data-bind="text:($index()+1)"></td>
            <td data-bind="text:Account.Id"></td>
            <td data-bind="text:Account.Name"></td>
            <td data-bind="text:Account.Balance"></td>
            <!--<td>
                <ul data-bind="foreach: {data:Deposits, as:'Amount'}">
                    <li data-bind="text:(Account().Name + 'Deposited ' + Amount())"></li>
                </ul>
            </td>-->
        </tr>
    </tbody>
</table>

Solution

  • The code in the question worked for me. Below is a version that works for @alwaysVBNET. - It's basically the content of the code in the question with some minor modifications. I downloaded KO 3.4.2 from http://knockoutjs.com/downloads/knockout-3.4.2.js

    The main change is the use of the temp variable to instantiate Account objects before adding them to the observable array. I will be interested if someone can explain why this should make a difference.

    <!doctype html>
    <html>
    <head>
    <title>KO js test</title>
    <script src=./knockout-3.4.2.js></script>
    
    </head>
    <body>
    <table>
        <thead>
            <tr>
                <th>S.No</th>
                <th>ID</th>
                <th>Name</th>
                <th>Balance</th>
            </tr>
        </thead>
        <tbody data-bind="foreach: {data:Accounts, as:'Account'}">
            <tr>
                <td data-bind="text:($index()+1)"></td>
                <td data-bind="text:Account.Id"></td>
                <td data-bind="text:Account.Name"></td>
                <td data-bind="text:Account.Balance"></td>
                <td>
                    <ul data-bind="foreach: {data:Deposits, as:'Amount'}">
                        <li data-bind="text:(Account.Name + 'Deposited ' + Amount)"></li>
                    </ul>
                </td>
            </tr>
        </tbody>
    </table>
    <script>
        "use strict";
        function Account(id, name, balance, deposits) {
            var self = this;
            self.Id = id;
            self.Name = name;
            self.Balance = balance;
            self.Deposits = deposits;
        }
        var MyAccountViewModel = function ()
        {
            var self = this;
            self.Accounts = ko.observableArray();
            var temp = new Account(1, "A1", 100, [1,2]);
            self.Accounts.push(temp);
            temp = new Account(2, "A2", 200, [2]);
            self.Accounts.push(temp);
            temp = new Account(3, "A3", 300, [2, 3]);
            self.Accounts.push(temp);
            temp = new Account(4, "A4", 400, [2,3]);
            self.Accounts.push(temp);
        }
        ko.applyBindings(new MyAccountViewModel());
    </script>
    </body>
    </html>