Knockout.js 让淘汰赛的例子发挥作用

Knockout.js 让淘汰赛的例子发挥作用,knockout.js,Knockout.js,看了之后,我决定这对于复杂的UI页面来说是非常好的 我通读了一遍。 然后我发现。所以我想建立一个类似Ryan的例子 它将显示一张桌子。表格的每一行都有一个预算。 用户可以输入每个季度的值。 预算减去季度之和将得出剩余金额。 如果剩余金额不是零,则该行将应用一个类。 该类会将背景颜色变为红色。 如果任何行的剩余值不等于零,则“保存”按钮将被禁用 我开始工作的是数据的初始显示 不起作用的是: 所有行都被读取,即使一行剩余零 当季度值更改时,剩余值不会更改 “保存”按钮从未启用 用于保存的Json不

看了之后,我决定这对于复杂的UI页面来说是非常好的

我通读了一遍。 然后我发现。所以我想建立一个类似Ryan的例子

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

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

不起作用的是:

  • 所有行都被读取,即使一行剩余零
  • 当季度值更改时,剩余值不会更改
  • “保存”按钮从未启用
  • 用于保存的Json不正确
代码可以在中找到,也可以在下面找到

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

table.pretty{
利润率:1米1米1米2米;
背景:白烟;
边界塌陷:塌陷;
}  
table.pretty th,table.pretty td{
边框:1px纯银;
填充:0.2米;
}  
表1.1{
背景:gainsboro;
文本对齐:左对齐;
}  
表1.1{
左边距:继承;
保证金权利:继承;
}  
.RowError{
背景色:红色;
颜色:白色;
}  
然后是一种观点:



数组中有行
我可以灵活地从服务器更改数据结构。
只要可以从服务器加载viewModel,我就可以灵活地构建viewModel 我对桌子的构造很灵活。

随着Q1-Q4值的变化,行变化的剩余值
如果剩余,行将变为红色!=0
在所有行的剩余值为0之前无法保存。

猫名 预算 Q1Amt Q2Amt Q3Amt Q4Amt 剩下的
还有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);
函数SendDataToServer(){
//构建要通过json发送的数据
var prepDataToSend=ko.toJS(viewModel.catagorydeails);
var mapDataForServer=ko.utils.arrayMap(prepDataToSend,函数(项){
删除item.CatName;
删除项目。剩余;
退货项目;
});
$(“#ForServer”).val(mapDataForServer);
//如果未调试,则返回true并删除警报。
警报(mapDataForServer);
返回false;
}
//来自服务器的数据
//var dataFromServer=;
//目前的硬代码
var dataFromServer=[
{“CatId”:1000,“CatName”:“汽车蜡”,“Q1Amt”:50,“Q2Amt”:60,“Q3Amt”:90,“Q4Amt”:80,“预算”:280},
{“CatId”:2000,“CatName”:“汽车擦拭工”,“Q1Amt”:20,“Q2Amt”:40,“Q3Amt”:60,“Q4Amt”:80,“预算”:200},
{“CatId”:3333,“CatName”:“换油”,“Q1Amt”:30,“Q2Amt”:70,“Q3Amt”:90,“Q4Amt”:10,“预算”:200},
{“CatId”:4040,“CatName”:“Gas”,“Q1Amt”:0,“Q2Amt”:0,“Q3Amt”:0,“Q4Amt”:0,“BudgetAmt”:3000}
];
//每行类别的构造函数(添加obserbale)
功能oneCat(CatId、CatName、Q1Amt、Q2Amt、Q3Amt、Q4Amt、BudgetAmt){
this.CatId=CatId;
this.CatName=CatName;
此Q1Amt=可观察的ko(Q1Amt);
此Q2Amt=可观察的ko(Q2Amt);
this.Q3Amt=ko.可观察(Q3Amt);
此Q4Amt=可观测的ko(Q4Amt);
this.BudgetAmt=ko.可观察(BudgetAmt);
this.Remaining=ko.dependenttobservable(函数(){
var total=此.BudgetAmt();
总计=总计-此.Q1Amt();
总计=总计-此.Q2Amt();
总计=总计-此.Q3Amt();
总计=总计-此.Q4Amt();
返回总数;
},这个);
}
var mappedFromServer=ko.utils.arrayMap(dataFromServer,函数(项){
返回新的oneCat(item.CatId、item.CatName、item.Q1Amt、item.Q2Amt、item.Q3Amt、item.Q4Amt、item.BudgetAmt);
});
//这是我的数据模型
var viewModel={
分类详细信息:ko.observableArray([])
};
//加上剩余的总数
viewModel.totalRemaining=ko.DependentToServable(函数(){
var合计=0;
ko.utils.arrayForEach(this.catagoryDetails(),函数(项){
var值=parseInt(剩余项,10);
如果(!isNaN(值)){
总+=价值;
}
});
返回总数;
},视图模型);
viewModel.catagoryDetails(mappedFromServer);
//使用模型视图模型启用“敲除”
应用绑定(视图模型);
看看这个:

主要问题是如何访问可观察对象。如果您只是将可观察对象传递给
数据绑定
,那么它将为您打开它。但是,如果要传递一个表达式,则需要将可观察对象作为函数访问(就像在实际的JavaScript中一样)

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

data bind=“css:{rowrerror:Remaining()!=0}”

data bind=“enable:totalRemaining()==0”

在您的TotalResisting DependentToServable中,您需要访问剩余服务,如:

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

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

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