循环遍历具有可观察属性的 Knockout 可观察对象数组
Posted
技术标签:
【中文标题】循环遍历具有可观察属性的 Knockout 可观察对象数组【英文标题】:Loop through Knockout observable array of objects with observable properties 【发布时间】:2019-06-02 15:39:22 【问题描述】:在我的应用程序中,我需要。这样我就可以将每个对象发布回服务器。
我可以访问我的模型,但我无法访问我想将其发回服务器的子元素。
我的客户代码是
self.postAllReqs = function(self)
self.error(''); // Clear error message
var model = ko.toJSON(self.Reqs); // convert to json
for (var item in model)
ajaxHelper(reqsUri, 'POST', item).fail(function (jqXHR, textStatus, errorThrown)
self.error(errorThrown);
)
请问如何访问子元素?
我的视图模型的提取
function ReqsTest(rt)
rt = rt || ;
var self = this;
self.id = ko.observable(rt.ID || 0);
self.requisition = ko.observable(rt.Requisition || "");
self.reqnStatus = ko.observable(rt.ReqnStatus || "");
self.dateReqnRaised = ko.observable(rt.DateReqnRaised|| null);
self.reqnValue = ko.observable(rt.ReqnValue || null);
self.approvedValue = ko.observable(rt.ApprovedValue || null);
self.originator = ko.observable(rt.Originator || "");
self.origName = ko.observable(rt.OrigName || "");
self.origEmail = ko.observable(rt.OrigEmail || "");
self.line = ko.observable(rt.Line || 0.00);
self.indx = ko.observable(rt.INDX || 0);
self.dateReqnRaisedL = ko.observable(rt.DateReqnRaisedL || null);
self.reqStatus = ko.observable(rt.ReqStatus || "");
//self.reqBackground = ko.observable(rt.ReqBackground || "");
//Computed observables
self.reqBackground = ko.computed(function ()
// get variable
var status = self.reqStatus();
if (status == "A") return "card-heading bg-success text-white";
else if (status == "D") return "card heading bg-secondary";
else if (status == "R") return "card heading bg-warning";
else if (status == "E") return "card heading bg-danger";
else
return "card-heading bg-primary text-white";
)
self.reqStatusLabel = ko.computed(function ()
// get variable
var status = self.reqStatus();
if (status == "A") return "Approved";
else if (status == "D") return "Declined - put on hold";
else if (status == "R") return "Routing On";
else if (status == "E") return "Erase On Syspro";
else
return "Awaiting Approval";
)
self.approvalBtn = ko.computed(function ()
// get variable
var status = self.reqStatus();
if (status == "A") return "css: button btn-secondary ";
else
return "btn btn-success ";
)
self.approvalBtnLbl = ko.computed(function ()
// get variable
var status = self.reqStatus();
if (status == "W") return "Approve";
else
return "UnApprove";
)
self.declineBtnLbl = ko.computed(function ()
// get variable
var status = self.reqStatus();
if (status == "D") return "UnDecline";
else
return "Decline";
)
self.deleteBtnLbl = ko.computed(function ()
// get variable
var status = self.reqStatus();
if (status == "E") return "Restore";
else
return "Erase";
)
// Functions
//show details alert
$(".btn").on("click", function ()
$(".alert").removeClass("in").show();
$(".alert").delay(200).addClass("in").fadeOut(2000);
);
function ReqsViewModel ()
var self = this;
self.Reqs = ko.observableArray([]);
self.error = ko.observable();
var reqsUri = '/api/ReqsTests/';
function ajaxHelper(uri, method, data)
self.error(''); // Clear error message
return $.ajax(
type: method,
url: uri,
dataType: 'json',
contentType: 'application/json',
data: data ? JSON.stringify(data) : null
).fail(function (jqXHR, textStatus, errorThrown)
self.error(errorThrown);
);
function getAllReqs()
ajaxHelper(reqsUri, 'GET').done(function (data)
// Build the ReqsTest objects
var reqs = ko.utils.arrayMap(data, function (rt)
return new ReqsTest(rt);
);
self.Reqs(reqs);
);
【问题讨论】:
【参考方案1】:从我所提供的代码可以看出,没有任何东西调用 getAllReqs 作为 ReqsViewModel 的私有函数。
我不太清楚您的问题是什么,因此我使用您的示例代码创建了一个快速演示,以展示您如何与数组中的项目进行交互。
var app = ;
function ReqsTest(rt, saveItemFn)
rt = rt || ;
var self = this;
self.id = ko.observable(rt.ID || 0);
self.requisition = ko.observable(rt.Requisition || "");
self.reqnStatus = ko.observable(rt.ReqnStatus || "");
self.dateReqnRaised = ko.observable(rt.DateReqnRaised || null);
self.reqnValue = ko.observable(rt.ReqnValue || null);
self.approvedValue = ko.observable(rt.ApprovedValue || null);
self.originator = ko.observable(rt.Originator || "");
self.origName = ko.observable(rt.OrigName || "");
self.origEmail = ko.observable(rt.OrigEmail || "");
self.line = ko.observable(rt.Line || 0.00);
self.indx = ko.observable(rt.INDX || 0);
self.dateReqnRaisedL = ko.observable(rt.DateReqnRaisedL || null);
self.reqStatus = ko.observable(rt.ReqStatus || "");
//self.reqBackground = ko.observable(rt.ReqBackground || "");
//Computed observables
self.reqBackground = ko.computed(function()
// get variable
var status = self.reqStatus();
if (status == "A")
return "card-heading bg-success text-white";
else if (status == "D")
return "card heading bg-secondary";
else if (status == "R")
return "card heading bg-warning";
else if (status == "E")
return "card heading bg-danger";
else
return "card-heading bg-primary text-white";
)
self.reqStatusLabel = ko.computed(function()
// get variable
var status = self.reqStatus();
if (status == "A")
return "Approved";
else if (status == "D")
return "Declined - put on hold";
else if (status == "R")
return "Routing On";
else if (status == "E")
return "Erase On Syspro";
else
return "Awaiting Approval";
)
self.approvalBtn = ko.computed(function()
// get variable
var status = self.reqStatus();
if (status == "A")
return "css: button btn-secondary ";
else
return "btn btn-success ";
)
self.approvalBtnLbl = ko.computed(function()
// get variable
var status = self.reqStatus();
if (status == "W")
return "Approve";
else
return "UnApprove";
)
self.approve = function()
if (self.reqStatus() == 'W')
self.reqStatus("A");
else
self.reqStatus("W");
saveItemFn(self);
self.declineBtnLbl = ko.computed(function()
// get variable
var status = self.reqStatus();
if (status == "D")
return "UnDecline";
else
return "Decline";
)
self.deleteBtnLbl = ko.computed(function()
// get variable
var status = self.reqStatus();
if (status == "E")
return "Restore";
else
return "Erase";
)
// Functions
//show details alert
$(".btn").on("click", function()
$(".alert").removeClass("in").show();
$(".alert").delay(200).addClass("in").fadeOut(2000);
);
function dataService(serviceUrl)
var url = serviceUrl;
function getData()
// do ajax call here
return
done: function(fn)
return fn(app.externalData);
function saveItem(item)
// add posting to server here.
alert("Saving item: " + item.id());
return
getData: getData,
saveItem: saveItem,
;
function ReqsViewModel(dataService)
var reqsUri = 'api/ReqsTests/';
var self = this;
self.Reqs = ko.observableArray([]);
self.error = ko.observable();
self.getAllReqs = getAllReqs;
function getAllReqs()
dataService.getData().done(function(data)
// Build the ReqsTest objects
var reqs = ko.utils.arrayMap(data, function(rt)
return new ReqsTest(rt, dataService.saveItem);
);
self.Reqs(reqs);
);
app.dataService = dataService;
app.externalData = [
ID: 1,
Requisition: "Requisition 1",
ReqnStatus: "A",
DateReqnRaised: "2019-01-01T11:00:00+11:00",
ReqnValue: 200.24,
ApprovedValue: 200,
Originator: "Slartibartfast",
OrigName: "Requisition 1",
OrigEmail: "test@test.com",
Line: 1.1,
INDX: 1,
DateReqnRaisedL: "2019-01-01T11:00:00+11:00",
ReqStatus: "A"
,
ID: 2,
Requisition: "Requisition 2",
ReqnStatus: "W",
DateReqnRaised: "2019-01-02T11:00:00+11:00",
ReqnValue: 300.24,
ApprovedValue: 300,
Originator: "Slartibartfast",
OrigName: "Requisition 2",
OrigEmail: "test@test.com",
Line: 2.2,
INDX: 2,
DateReqnRaisedL: "2019-01-02T11:00:00+11:00",
ReqStatus: "W"
];
var vm = new ReqsViewModel(app.dataService("/api/reqs/"));
vm.getAllReqs();
ko.applyBindings(vm);
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.2.1/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>Requistion</th>
<th>Raised</th>
<th></th>
</tr>
</thead>
<tbody data-bind="foreach: Reqs">
<tr>
<td data-bind="text: id"></td>
<td data-bind="text: requisition"></td>
<td data-bind="text: dateReqnRaised"></td>
<td><button class="btn btn-primary" data-bind="css: approvalBtn, text: approvalBtnLbl, click: approve">Approve</button></td>
</tr>
</tbody>
</table>
【讨论】:
以上是关于循环遍历具有可观察属性的 Knockout 可观察对象数组的主要内容,如果未能解决你的问题,请参考以下文章
Knockout.js:当可观察数组中的值发生变化时触发计算的最佳方法是啥
Knockout JS - 在没有 ko.mapping 的情况下观察数组的任何属性中的突变