Reputation: 2973
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:
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
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
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