背景:我很新MVC & Knockout.js,但我試圖趕上這些技術的速度。我正在使用EF6和Knockout.JS 3.2的MVC 5。連接MVC模型視圖和關聯的Knockout.js視圖模型
我有基於URL傳遞的ID,拉使用MVC一個「VoteAnswer」對象的詳細視圖:
例如,我可以到網址MYDOMAIN/VoteAnswers /細節/ 1,它會拉來自我的數據庫的信息正確(它拉取ID爲1的VoteAnswer)並顯示在我的Details視圖中。然而,我正在試圖連接我的Knockout.js「VoteAnswer」ViewModel以相同的方式運行,並遇到麻煩。
這裏是我的詳細信息視圖。(注意@ Html.DisplayFor(型號=> model.VoteAnswerId)等作品,並從我的數據庫顯示的數據
@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>
這裏是我的Knockout.Js視圖模型
// 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);
});
我知道我缺少的是初始化視圖模型與1的ID,但我想MVC模式已經有數據和knockout.js應該映射到這些數據,而無需再次通過向數據庫發送請求來手動初始化。我錯過了什麼?謝謝。
EDIT:添加溶液下面。我不確定我是如何解決這個問題的,但是現在是這樣。更新控制器以僅返回視圖而不查詢數據庫。 (否則我會擁有相同的數據的兩個數據庫調用。
// GET: VoteAnswers/Details/5
public ViewResult Details(int? id)
{
return View();
}
新增的API控制器,做查詢數據庫。
// 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);
}
在我看來(.cshtml文件)我引用我的淘汰賽。 JS模型視圖,示意如下:
<!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>
更新了我的視圖模型腳本訪問基於URL ID數據庫
// 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());
});
ViewModel javascript是在單獨的JS文件中,還是直接內置於剃鬚刀頁面? – 2014-09-04 22:05:09
你嘗試過'ko.applyBindings(new VoteAnswerVM());'這樣的事情 – 2014-09-05 06:41:59
@Robert - 是的,它是一個單獨的JS文件,我確認它正在加載。我還驗證了,如果手動傳入參數,viewModel和knockout代碼將起作用。例如,如果我初始化爲:'ko.applyBindings(new VoteAnswerVM(1,「My Text」,true));'並將功能更改爲除這些屬性外。 – cmartin 2014-09-05 12:03:24