Contexte: Je suis assez nouveau à MVC & Knockout.js mais j'essaie de se mettre au courant de ces technologies. J'utilise MVC 5 avec EF6 et Knockout.JS 3.2.Connexion MVC Model View avec Knockout.js associé ViewModel
J'ai une vue de détail qui tire un objet « VoteAnswer » en utilisant MVC basé sur l'ID passé dans l'URL:
Par exemple, je peux aller à l'url MyDomain/VoteAnswers/Détails/1 et il va tirer les informations de ma base de données correctement (Il tire un VoteAnswer avec l'ID de 1) et afficher dans ma vue Détails. Cependant, j'essaie de brancher mon ViewModel "VoteAnswer" de Knockout.js pour fonctionner de la même manière et j'ai des problèmes.
Voici mon Détails Vue:. (Notez le @ Html.DisplayFor (modèle => model.VoteAnswerId) etc travaux et affiche les données de ma base de données
@model AM_SPA_TestSite.Models.VoteAnswer
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Details</title>
<script src="~/KnockoutViewModels/VoteAnswers.js"></script>
</head>
<body>
<div>
<h4>VoteAnswer</h4>
<hr />
<table>
<tr>
<td>Id</td>
<td data-bind="text: id"></td>
</tr>
<tr>
<td>Display Text</td>
<td data-bind="text: isActive"></td>
</tr>
<tr>
<td>IsActive</td>
<td data-bind="text: displayText"></td>
</tr>
</table>
<table>
<tr>
<td>Id</td>
<td><input type="text" data-bind="value: id" /></td>
</tr>
<tr>
<td>Display Text</td>
<td><input type="text" data-bind="value: displayText" /></td>
</tr>
<tr>
<td>IsActive</td>
<td><input type="text" data-bind="value: isActive" /></td>
</tr>
</table>
<table>
<tr>
<td>Id</td>
<td>@Html.DisplayFor(model => model.VoteAnswerId)</td>
</tr>
<tr>
<td>Display Text</td>
<td>@Html.DisplayFor(model => model.DisplayText)</td>
</tr>
<tr>
<td>IsActive</td>
<td>@Html.DisplayFor(model => model.IsActive)</td>
</tr>
</table>
</div>
Voici mon Knockout.Js ViewModel
// VoteAnswer ViewModel
var VoteAnswerVM = {
id: ko.observable(),
displayText: ko.observable(),
isActive: ko.observable(),
SaveVoteAnswer: function() {
$.ajax({
url: '/VoteAnswers/Create',
type: 'post',
dataType: 'json',
data: ko.toJSON(this),
contentType: 'application/json',
success: function (result) {
},
error: function (err) {
if (err.responseText == "Creation Failed")
{ window.location.href = '/VoteAnswers/Index/'; }
else {
alert("Status:" + err.responseText);
window.location.href = '/VoteAnswers/Index/';;
}
},
complete: function() {
window.location.href = '/VoteAnswers/Index/';
}
});
}
};
//Go
$(document).ready(function() {
//initialize and create new VoteAnswerVM by URL value here?
ko.applyBindings(VoteAnswerVM);
});
Je sais ce que je suis absent initialise la ViewModel avec l'ID de 1, mais je pensais le modèle MVC a déjà les données et la knockout.js DEVRAIT correspondre à ces données sans initialiser manuellement en envoyant à nouveau une requête à la base de données. Qu'est-ce que je rate? Merci.
EDIT: Ajoutésolutionci-dessous. Je ne suis pas sûr que je sois fixé sur cette approche mais c'est ici. Mise à jour du contrôleur pour retourner uniquement une vue et ne pas interroger la base de données. (Sinon je l'aurais deux appels de base de données pour les mêmes données.
// GET: VoteAnswers/Details/5
public ViewResult Details(int? id)
{
return View();
}
Ajouté un contrôleur API qui fait interroger la base de données.
// GET: api/VoteAnswers/5
[ResponseType(typeof(VoteAnswer))]
public async Task<IHttpActionResult> GetVoteAnswer(int id)
{
VoteAnswer voteAnswer = await db.VoteAnswers.FindAsync(id);
if (voteAnswer == null)
{
return NotFound();
}
return Ok(voteAnswer);
}
À mon avis (fichier .cshtml) Je référence mon knock-out. js MODELVIEW, View est ci-dessous.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Details</title>
<script src="~/KnockoutViewModels/VoteAnswers.js"></script>
</head>
<body>
<div>
<h4>VoteAnswer</h4>
<hr />
<table>
<tr>
<td>Id</td>
<td data-bind="text: VoteAnswerId"></td>
</tr>
<tr>
<td>Display Text</td>
<td data-bind="text: IsActive"></td>
</tr>
<tr>
<td>IsActive</td>
<td data-bind="text: DisplayText"></td>
</tr>
</table>
<table>
<tr>
<td>Id</td>
<td><input type="text" data-bind="value: VoteAnswerId" /></td>
</tr>
<tr>
<td>Display Text</td>
<td><input type="text" data-bind="value: DisplayText" /></td>
</tr>
<tr>
<td>IsActive</td>
<td><input type="text" data-bind="value: IsActive" /></td>
</tr>
</table>
</div>
<div id="error"></div>
</body>
</html>
mis à jour mon script ViewModel pour accéder à la base de données basée sur l'ID URL
// VoteAnswer ViewModel
var VoteAnswer = function() {
var self = this;
self.VoteAnswerId = ko.observable();
self.DisplayText = ko.observable();
self.IsActive = ko.observable();
self.SaveVoteAnswer = function() {
$.ajax({
url: '/VoteAnswers/Create',
type: 'post',
dataType: 'json',
data: ko.toJSON(this),
contentType: 'application/json',
success: function (result) {
},
error: function (err) {
if (err.responseText == "Creation Failed")
{ window.location.href = '/VoteAnswers/Index/'; }
else {
alert("Status:" + err.responseText);
window.location.href = '/VoteAnswers/Index/';;
}
},
complete: function() {
window.location.href = '/VoteAnswers/Index/';
}
});
}
self.load = function (id) {
if (id != 0) {
$.ajax({
url: '/api/VoteAnswers/' + id,
type: 'get',
data: ko.toJSON(this),
contentType: 'application/json',
success: function(data) {
self.VoteAnswerId = ko.observable(data.voteAnswerId);
self.DisplayText = ko.observable(data.displayText);
self.IsActive = ko.observable(data.isActive);
ko.applyBindings(self);
},
error: function(err) {
if (err.responseText == "Creation Failed") {
window.location.href = '/VoteAnswers/Index/';
} else {
$("#error").text("Status:" + err.responseText);
//window.location.href = '/VoteAnswers/Index/';;
}
},
complete: function() {
//window.location.href = '/VoteAnswers/Index/';
}
});
} else {
window.location.href = '/VoteAnswers/Index/';
}
}
};
function GetURLParameter() {
var sPageUrl = window.location.href;
var indexOfLastSlash = sPageUrl.lastIndexOf("/");
if (indexOfLastSlash > 0 && sPageUrl.length - 1 != indexOfLastSlash)
return sPageUrl.substring(indexOfLastSlash + 1);
else
return 0;
}
//Go
$(document).ready(function() {
//initialize and create new VoteAnswerVM by URL value here?
var viewModel = new VoteAnswer();
viewModel.load(GetURLParameter());
});
Le ViewModel est-il javascript dans un fichier JS séparé, ou intégré directement dans la page du rasoir? –
avez-vous essayé 'ko.applyBindings (nouveau VoteAnswerVM());' quelque chose comme ça –
@Robert - oui c'est un fichier JS distinct, j'ai vérifié qu'il est en cours de chargement. J'ai également vérifié que les codes viewModel et knockout fonctionnent si je passe manuellement les paramètres. Par exemple si j'ai initialisé comme: 'ko.applyBindings (nouveau VoteAnswerVM (1, "Mon texte", vrai));' et changé la fonction à l'exception de ces propriétés. – cmartin