gpt4 book ai didi

knockout.js - 让 Knockout 示例发挥作用

转载 作者:行者123 更新时间:2023-12-01 13:01:21 33 4
gpt4 key购买 nike

看完Knockout.JS video with Steve Sanderson我认为这对于复杂的 UI 页面非常有用。

我完成了 the live examples并通读the documentation .然后我找到了Ryan Niemeyer's great article .所以我想构建一个类似于 Ryan 的示例。

它会显示一个表格。表格的每一行都有一个预算。
用户可以输入每个季度的值。
预算减去季度总和得到剩余金额。
如果剩余金额不为零,则该行将应用一个类。该类会将背景颜色变为红色。
如果任何行的剩余值不等于零,则保存按钮将被禁用。

我开始工作的是数据的初始显示。

不起作用的是:

  • 所有行都被读取,即使是一个,剩余零。
  • 当季度值发生变化时,剩余值不变。
  • 保存按钮从未启用。
  • 保存的 Json 不正确。

代码可以在this fiddle中找到以及以下内容。

首先,一些 CSS 使事情看起来正确:

   table.pretty {  
margin: 1em 1em 1em 2em;
background: whitesmoke;
border-collapse: collapse;
}
table.pretty th, table.pretty td {
border: 1px silver solid;
padding: 0.2em;
}
table.pretty th {
background: gainsboro;
text-align: left;
}
table.pretty caption {
margin-left: inherit;
margin-right: inherit;
}
.RowError {
background-color: Red;
color: White;
}

然后是 View :

<br /><br />  
<p>
There are <span data-bind="text: catagoryDetails().length">&nbsp;</span> rows in array<br />
I am flexible on changing the structure of data from server.<br />
I am flexible on how viewModel is built as long as it can be loaded from server <br />
I am flexible on how table is built.
</p>
<p>
As Q1-Q4 values change the Remaining for row changes <br />
Row turns red if Remaining != 0 <br />
Unable to Save until all rows have a remaining of 0.<br>
</p>

<table id="pretty" >
<thead>
<tr>
<th>CatName</th>
<th>Budget</th>
<th>Q1Amt</th>
<th>Q2Amt</th>
<th>Q3Amt</th>
<th>Q4Amt</th>
<th>Remaining</th>
</tr>
</thead>
<tbody data-bind="template: { name: 'catagoryDetailRowTemplate', foreach: catagoryDetails }"></tbody>
</table>

<script type="text/html" id="catagoryDetailRowTemplate">
<tr data-bind="css: { RowError: Remaining != 0 }">
<td>
<input type="hidden" data-bind="value: CatId"/>
<span data-bind="text: CatName"> </span>
</td>

<td><span data-bind="text: BudgetAmt"> </span></td>
<td><input data-bind="value: Q1Amt"/></td>
<td><input data-bind="value: Q2Amt"/></td>
<td><input data-bind="value: Q3Amt"/></td>
<td><input data-bind="value: Q4Amt"/></td>
<td><span data-bind="text: Remaining"> </span></td>
</tr>
</script>
<form action="ActionOnServer" >
<input type="hidden" value="Not Set" id="ForServer" name="ForServer"/>
<input type="submit" onclick="SendDataToServer()" value="Save" data-bind="enable: totalRemaining = 0" />
<input type="button" onclick="alert('I would do cancel action')" value="Cancel" />
</form>

和 Javascript:

   function SendDataToServer() {
// build data to send via json
var prepDataToSend = ko.toJS(viewModel.catagoryDetails);
var mapDataForServer = ko.utils.arrayMap(prepDataToSend, function(item) {
delete item.CatName;
delete item.Remaining;
return item;
});

$("#ForServer").val(mapDataForServer);

// if not debug return true and remove alert.
alert(mapDataForServer);
return false;
}

// data from the server
// var dataFromServer = <%= new JavaScriptSerializer().Serialize(Model) %>;

// Hard code for now
var dataFromServer = [
{ "CatId": 1000, "CatName": "Car wax", "Q1Amt": 50, "Q2Amt": 60, "Q3Amt": 90, "Q4Amt": 80, "BudgetAmt": 280 },
{ "CatId": 2000, "CatName": "Car Wippers", "Q1Amt": 20, "Q2Amt": 40, "Q3Amt": 60, "Q4Amt": 80, "BudgetAmt": 200 },
{ "CatId": 3333, "CatName": "Oil Change", "Q1Amt": 30, "Q2Amt": 70, "Q3Amt": 90, "Q4Amt": 10, "BudgetAmt": 200 },
{ "CatId": 4040, "CatName": "Gas", "Q1Amt": 0, "Q2Amt": 0, "Q3Amt": 0, "Q4Amt": 0, "BudgetAmt": 3000 }
];

// constructor for each row of categories ( adds obserbale )
function oneCat(CatId, CatName, Q1Amt, Q2Amt, Q3Amt, Q4Amt, BudgetAmt) {
this.CatId = CatId;
this.CatName = CatName;
this.Q1Amt = ko.observable(Q1Amt);
this.Q2Amt = ko.observable(Q2Amt);
this.Q3Amt = ko.observable(Q3Amt);
this.Q4Amt = ko.observable(Q4Amt);
this.BudgetAmt = ko.observable(BudgetAmt);
this.Remaining = ko.dependentObservable(function () {
var total = this.BudgetAmt();
total = total - this.Q1Amt();
total = total - this.Q2Amt();
total = total - this.Q3Amt();
total = total - this.Q4Amt();
return total;
}, this);
}

var mappedFromServer = ko.utils.arrayMap(dataFromServer, function (item) {
return new oneCat(item.CatId, item.CatName, item.Q1Amt, item.Q2Amt, item.Q3Amt, item.Q4Amt, item.BudgetAmt);
});

// Here's my data model
var viewModel = {
catagoryDetails: ko.observableArray([])
};

// add total of remaining
viewModel.totalRemaining = ko.dependentObservable(function () {
var total = 0;
ko.utils.arrayForEach(this.catagoryDetails(), function (item) {
var value = parseInt(item.Remaining, 10);
if (!isNaN(value)) {
total += value;
}
});
return total;
}, viewModel);

viewModel.catagoryDetails(mappedFromServer);

// turn on Knockout with the model viewModel
ko.applyBindings(viewModel);

最佳答案

看看这个:http://jsfiddle.net/rniemeyer/qmXWE/

主要问题是您如何访问您的可观察对象。如果您只是将 observable 传递给 data-bind,那么它会为您解包。但是,如果您要传递表达式,则需要将可观察对象作为函数访问(就像在实际的 JavaScript 中一样)。

因此,您必须进行的更改是:

data-bind="css: { RowError: Remaining() != 0 }"

data-bind="enable: totalRemaining() == 0"

并且在您的 totalRemaining dependentObservable 中,您需要像这样访问 remaining:

var value = parseInt(item.Remaining(), 10);

最后,对于您的 JSON 问题,我认为处理它的一个好方法是将 toJSON 方法添加到您的 oneCat 类型。您可以在那里删除不需要的属性。它看起来像:

oneCat.prototype.toJSON = function() {
var copy = ko.toJS(this); //easy way to get a copy
delete copy.CatName;
delete copy.Remaining;
return copy;
}

然后,您可以只在您的对象上使用 ko.toJSON,当调用 JSON.stringify 时,只要它看到 oneCat 就会使用您的 toJSON 函数。

希望这对您有所帮助。

关于knockout.js - 让 Knockout 示例发挥作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5807118/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com