0
votes

I have the following View and Script:

@{
    ViewBag.Title = "Games";
}

<h2>Games</h2>
<table class="table-bordered">
    <thead>
        <tr>
            <th>Course</th>
            <th>Date</th>
            <th>Player</th>
            <th>Hole 1</th>
            <th>Hole 2</th>
            <th>Hole 3</th>
            <th>Hole 4</th>
            <th>Hole 5</th>
            <th>Hole 6</th>
            <th>Hole 7</th>
            <th>Hole 8</th>
            <th>Hole 9</th>
        </tr>
    </thead>
    <tbody data-bind="foreach: GameList">
        <tr>
            <td data-bind="text: CourseName"></td>
            <td data-bind="text: Date"></td>
        </tr>
        <!-- ko foreach: GameEntry -->
        <tr>
            <td></td>
            <td></td>
            <td data-bind="text:PlayerName"></td>
            <td data-bind="text:HoleOneScore"></td>
            <td data-bind="text:HoleTwoScore"></td>
            <td data-bind="text:HoleThreeScore"></td>
            <td data-bind="text:HoleFourScore"></td>
            <td data-bind="text:HoleFiveScore"></td>
            <td data-bind="text:HoleSixScore"></td>
            <td data-bind="text:HoleSevenScore"></td>
            <td data-bind="text:HoleEightScore"></td>
            <td data-bind="text:HoleNineScore"></td>
        </tr>
        <!-- /ko -->
    </tbody>
</table>
<script>
    function Game(data){
        var self = this;
        self.CourseName = ko.observable(data.CourseName);
        self.Date = ko.observable(data.Date);
        self.GameEntries = ko.observableArray([]);
    }

    function GameEntry(data){
        var self = this;
        self.PlayerName = ko.observable(data.PlayerName);
        self.HoleOneScore = ko.observable(data.HoleOneScore);
        self.HoleTwoScore = ko.observable(data.HoleTwoScore);
        self.HoleThreeScore = ko.observable(data.HoleThreeScore);
        self.HoleFourScore = ko.observable(data.HoleFourScore);
        self.HoleFiveScore = ko.observable(data.HoleFiveScore);
        self.HoleSixScore = ko.observable(data.HoleSixScore);
        self.HoleSevenScore = ko.observable(data.HoleSevenScore);
        self.HoleEightScore = ko.observable(data.HoleEightScore);
        self.HoleNineScore = ko.observable(data.HoleNineScore);
    }

    function ViewModel() {
        var self = this;
        self.GameList = ko.observableArray([]);

        $.getJSON("/Games/GetGames", function (allData) {
            var mappedTasks = $.map(allData, function (item) { return new Game(item) });
            //console.log(mappedTasks);
            self.GameList(mappedTasks);
        });
    }

    $(document).ready(function () {       
        ko.applyBindings(new ViewModel());
    });
</script>

However when I try and bind my data which looks like the following:

{
    "CourseName": "Green Hills",
    "Date": "2013-04-02T16:33:21.943",
    "GameEntries": [
      {
        "PlayerName": "Chris Camp",
        "HoleOneScore": 4,
        "HoleTwoScore": 5,
        "HoleThreeScore": 6,
        "HoleFourScore": 3,
        "HoleFiveScore": 4,
        "HoleSixScore": 4,
        "HoleSevenScore": 4,
        "HoleEightScore": 5,
        "HoleNineScore": 3
      }
    ]
  },
  {
    "CourseName": "Green Hills",
    "Date": "2015-05-01T13:08:41.783",
    "GameEntries": []
  },
  {
    "CourseName": "Green Hills",
    "Date": "2015-05-01T13:13:45.34",
    "GameEntries": [
      {
        "PlayerName": "Chris Camp",
        "HoleOneScore": 4,
        "HoleTwoScore": 3,
        "HoleThreeScore": 4,
        "HoleFourScore": 7,
        "HoleFiveScore": 5,
        "HoleSixScore": 2,
        "HoleSevenScore": 1,
        "HoleEightScore": 4,
        "HoleNineScore": 6
      }
    ]
  }

I am met with this error:

Uncaught ReferenceError: Unable to process binding "foreach: function (){return GameEntry }"
Message: Unable to process binding "text: function (){return PlayerName }"
Message: PlayerName is not defined

Which I believe is due to the fact that the GameEntries array of the GameList>Game observable is not being populated. What is the correct way to bind this type of JSON output to a view model?

2

2 Answers

2
votes

I saw a couple of things to change

<!-- ko foreach: GameEntries -->

and

function Game(data) {
var self = this;
    self.CourseName = ko.observable(data.CourseName);
    self.Date = ko.observable(data.Date);
    var entries = $.map(data.GameEntries, function (entry) {
        return new GameEntry(entry);
    });
    self.GameEntries = ko.observableArray(entries);
}

Check out this JSFiddle http://jsfiddle.net/efpx08ta/2/

1
votes

<!-- ko foreach: GameEntry -->

should be

<!-- ko foreach: GameEntries -->

You bind to the property, not the type.