Reputation: 463
I have a knockout viewmodel which is updated with JSON data received from the server for each button click and would like to refresh the binding based on the changes to viewModel. I am using knockout mapping to convert the JSON to KO observables.
My question is the bindings are not refreshed when the viewmodel is updated on button click
The sample fiddle is here
JS:
function getPlayersAsJSON(country) {
var players = null;
if (country === 'spain') {
players = $('#spainText').val();
} else if (country === 'swiss') {
players = $('#swissText').val();
}
return players;
}
var viewModel = {
players: ko.observableArray()
};
$(function () {
$('#btnSearch').click(function () {
var playerDataJSON = getPlayersAsJSON($('#drpCountry').val());
var playerData = ko.mapping.fromJSON(playerDataJSON);
console.log(playerDataJSON);
console.log(playerData);
console.log(playerData());
viewModel.players(playerDataJSON);
});
});
ko.applyBindings(viewModel);
HTML:
<div>JSON Data for Spain
<br/>
<textArea id="spainText" rows="4" cols="50">[{"Name": "Nadal","Age": 28},{"Name": "Ferrer","Age": 32},{"Name": "Ferrer", "Age": 29}]</textArea>
<br/>JSON Data for Swiss
<br/>
<textArea id="swissText" rows="4" cols="50">[{"Name": "Federer","Age": 32},{"Name": "Wawiranka", "Age": 28}]</textArea>
</div>
<br/>
<div>Select Country
<br/>
<select id="drpCountry">
<option value="spain">spain</option>
<option value="swiss">swiss</option>
</select>
</div>
<input type="button" id="btnSearch" value="Search" />
<br/>
<table>
<thead>
<tr>
<th>Name</th>
</tr>
</thead>
<tbody data-bind="foreach: players">
<tr>
<td data-bind="text: $data.Name"></td>
<td data-bind="text: $data.Age"></td>
</tr>
</tbody>
</table>
Please let me know if you need more details
Upvotes: 2
Views: 9120
Reputation: 139758
If the input is an array then ko.mapping.fromJSON
will return a ko.observableArray
.
So you need to write playerData()
to unwrap the observable array otherwise you will end up your players
observable array holding another observable array:
var playerData = ko.mapping.fromJSON(playerDataJSON);
viewModel.players(playerData()); //unwrap the playerData
Demo JSFiddle.
As an alternative solution the mapping plugin supports to directly fill in an already existing observable arrays if the input is a JSON array, with the following syntax:
ko.mapping.fromJSON(playerDataJSON, {} /* empty options */, viewModel.players);
Demo JSFiddle.
Upvotes: 2