S. ten Brinke
S. ten Brinke

Reputation: 2973

Information from my object filled observable array won't show up in my view

I have found similair questions about the problem I'm having here on SO, but none of them fixed my problem.

When I load the page, I retrieve an array of objects from the database using AJAX. They have the properties ID,name and score.

The array will be put in a variable called hs.
When I console.log the variable hs, it logs the array with the objects inside, so that can not be the problem. (Right?)

Now, when I load the page, it doesn't show the information from those objects. That is the issue I'm experiencing!

This is a piece of my viewmodel:

 function initCanvas() {
    this.playerName = ko.observable("");
    this.chosenLevel = ko.observable();
    this.chosenDifficulty = ko.observable();

    this.availableLevels = ko.observableArray(['Mountains', 'Stars', 'Jungle']);
    this.difficulty = ko.observableArray(['Makkelijk', 'Normaal', 'Moeilijk']);
    this.highscores = ko.observableArray(hs);
    this.personalHighScore = ko.observable(localStorage.getItem("+score") || "Geen record!");

My HTML looks like this:

        <table>             
            <tbody data-bind="foreach: highscores">
                <tr>
                    <td><span data-bind="text: name"></span></td>
                    <td><span data-bind="text: score"></span></td>
                </tr>
            </tbody>
        </table>

Can you guys help me out? I'm a bit new at Knockout so please forgive me if this is a dumb question.

Edit

Here's some more information:

 hs = [];
    getHighScores();

function getHighScores() {
        var highScoreArray = [];
        $.ajax({
            url: "../php/score_server.php",
            data: {
                "action": "getScore"
            },

            type: 'GET',
            success: function (result) {
                var resultParsed = JSON.parse(result);
                $.each(resultParsed, function (key, value) {
                    hs.push(value);
                });
            },
            error: function (jqXHR, textStatus, errorThrown) {
                console.log(jqXHR);
                console.log(textStatus);
                console.log(errorThrown);
            },
            async: true
        });
    }

The result looks like this:

enter image description here

There's some other bugs as well that I can not fix, like the getHighScores() being fired twice, although I call it only once... And it doesn't matter what the score is, The PHP document I call with my sendHighScore() function will always put 9 in the database. But I might open another question for that later.

EDIT 2

$(document).ready(function () {
    var ctx = document.getElementById('canvas').getContext('2d'),
        cW = ctx.canvas.width,
        cH = ctx.canvas.height,
        animateInterval,
        P,
        hs = [],
        paused = false;
    getHighScores();
    ko.applyBindings(new initCanvas());

    function getHighScores() {
        var highScoreArray = [];
        $.ajax({
            url: "../php/score_server.php",
            data: {
                "action": "getScore"
            },

            type: 'GET',
            success: function (result) {
                var resultParsed = JSON.parse(result);
                $.each(resultParsed, function (key, value) {
                    hs.push(value);
                });
            },
            error: function (jqXHR, textStatus, errorThrown) {
                console.log(jqXHR);
                console.log(textStatus);
                console.log(errorThrown);
            },
            async: true
        });
    }
    function initCanvas() {
        this.playerName = ko.observable("");
        this.chosenLevel = ko.observable();
        this.chosenDifficulty = ko.observable();

        this.availableLevels = ko.observableArray(['Mountains', 'Stars', 'Jungle']);
        this.difficulty = ko.observableArray(['Makkelijk', 'Normaal', 'Moeilijk']);
        this.highscores = ko.observableArray(hs);
        this.personalHighScore = ko.observable(localStorage.getItem("+score") || "Geen record!");

Solution

My fixed HTML:

<table>                     
    <tbody data-bind="foreach: highscores">
        <tr>
            <td><span data-bind="text: name"></span></td>
            <td><span data-bind="text: score"></span></td>
        </tr>
    </tbody>
</table>

My fixed Javascript:

 function getHighScores() {
        var highScoreArray = [];
        $.ajax({
            url: "../php/score_server.php",
            data: {
                "action": "getScore"
            },

            type: 'GET',
            success: function (result) {

                var resultParsed = JSON.parse(result);
                $.each(resultParsed, function (key, value) {
                    hs.push(value);
                });
                ko.applyBindings(new initCanvas());
                $('#controls').find('input, select, button').prop('disabled', false);

            },

            error: function (jqXHR, textStatus, errorThrown) {
                console.log(jqXHR);
                console.log(textStatus);
                console.log(errorThrown);
            },
            async: true
        });
    }

Upvotes: 0

Views: 130

Answers (2)

Tony
Tony

Reputation: 1376

A better solution would be to set the observable arrays value. Currently you are sort of defeating the purpose of using knockout by waiting for the post to return. It would look something like this.

Replace:

ko.applyBindings(new initCanvas());

in your original example with:

var canvasViewModel = new initCanvas();
ko.applyBindings(canvasViewModel);

and then in your success callback you would want to set the value of the observable like this:

canvasViewModel.highscores(resultParsed);

instead of

$.each(resultParsed, function (key, value) {
   hs.push(value);
});
ko.applyBindings(new initCanvas());

Upvotes: 0

Bryant Miano
Bryant Miano

Reputation: 689

When you create your viewmodel (initCanvas) the array hs is empty because it has not waited for the ajax call to complete. On your success callback of your $.ajax is when you should ko.applybindings. That way you actually have data in hs for knockout to bind:

            success: function (result) {
                var resultParsed = JSON.parse(result);
                $.each(resultParsed, function (key, value) {
                    hs.push(value);
                });
                ko.applyBindings(new initCanvas());

            }

Upvotes: 1

Related Questions