请考虑以下事项:
(function($, ko){
var ViewModel = function() {
var self = this;
self.errorMessages = ko.observableArray([]);
self.desigItems = ko.observableArray([]);
self.frequencies = ko.observableArray([]);
}
var viewModel = new ViewModel();
var loadData = function() {
$.ddcApiGet('/widget/desigs.json', [], function(data) {
_processLoadedData(data);
}, viewModel.errorMessages);
}
var loadFrequencies = function() {
$.ddcApiGet('/widget/freqs.json', [], function(data) {
_processFrequenciesData(data);
}, viewModel.errorMessages);
}
var _processLoadedData = function(data) {
for (var i = 0; i < data.desig_options.length; i++) {
viewModel.desigItems.push(data.desig_options[i]);
}
}
var _processFrequenciesData = function(data) {
var frequencies = [];
// Get the list of frequencies.
for (var i = 0; i < data.frequency.length; i++) {
frequencies.push(data.frequency[i]);
}
// Push frequencies on to each of the design items in the list.
for (var i = 0; i < viewModel.desigItems.length; i++) {
viewModel.desigItems[i]['frequencies'] = frequencies
}
console.log(viewModel.desigItems());
}
var preBind = function() {
loadData();
loadFrequencies();
}
preBind();
ko.applyBindings(viewModel, $('#designnation-list-container')[0]);
})(jQuery, ko);
然后将其与以下视图相关联:
<h1>Hello World</h1>
<div id="designnation-list-container" data-bind="foreach: desigItems">
<div class="donor-js-wid-desig-opt donor-style-box donor-style-2col">
<h2 class="donor-js-desig-desc" data-bind="text: desc"> </h2>
<img class="donor-js-desig-logo donor-style-donation-image" alt="Web Desc 10000 - adding this" src="https://d36vh9gkg2fzwi.cloudfront.net/imageserver/be1b7b8e195587ff422c40750a6caa9f/10000_IPHONE_v1.JPG">
<form method="post" enctype="multipart/form-data" action="javascript:">
<input class="donor-js-wid-desig" type="hidden" name="gift_desig" value="10000">
<p class="donor-js-desig-shorttext" data-bind="html: shortdesc"> </p>
<p id="donor-js-donation-amount-label">
<label class="donor-style-label">Donation Amount</label>
</p>
<p>
<div data-bind="foreach: amount_options">
<label class="donor-js-amount-choice">
<input type="radio" class="donor-js-webware" name="gift_amt" data-bind="attr: {value: desc}, checked: selected"><span class="donor-js-currency-symbol">$</span> <span class="donor-js-amount" data-bind="text: desc"></span> <span class="donor-js-input-currency"></span><br>
</label>
</div>
<label>
<input type="radio" class="donor-js-other-amount-opt" name="gift_amt" value="other">
<span id="donor-js-other-label">Amount:</span>
<span class="donor-js-currency-symbol">$</span></label>
<input class="donor-js-other-amount-input" type="text" name="other_amt" onclick="$(this).closest('form').find('input[class=donor-js-other-amount-opt]').attr('checked', true);"> <span class="donor-js-input-currency"></span>
</p>
<p>
<select class="donor-js-wid-frequency" name="gift_freq" data-bind="options: frequencies, optionsText: desc, value: desc"></select>
</p>
<p id="donor-js-gift-notes" style="display:none">
<label class="donor-js-gift-note-label">Gift Notes
<textarea name="gift_note" class="donor-style-select" rows="2" cols="40"></textarea>
</label>
</p>
<p><input type="submit" class="donor-js-dona-submit button" value="Add to Cart"><input type="button" class="donor-js-desig-info donor-style-buttonlink" value="show more details">
</p></form>
<div class="donor-style-clearb"></div>
</div>
</div>
我知道很多东西,但我遇到一个特定功能的问题:_processFrequenciesData
看问题是我有一个选择元素:
<p>
<select class="donor-js-wid-frequency" name="gift_freq" data-bind="options: frequencies, optionsText: desc, value: desc"></select>
</p>
正如您在我发布的初始视图中看到的那样,这个select元素位于循环中,遍历self.desigItems
此功能中有console.log
(_processFrequenciesData
),但会返回:[]
你会想到,好吧可能没有提取数据,此时接受它,因为7个项目会被渲染到屏幕上。
我想要做的就是说,好的:将frequencies
的这个列表添加到每个desigItems
那么为什么当我console.log(viewModel.desigItems)
我得到一个空数组时,当视图遍历desigItems时,我得到了七件事?
答案 0 :(得分:1)
那么为什么当我
console.log(viewModel.desigItems())
我得到一个空数组时,当视图遍历desigItems时,我得到了七件事?
您在console.log(viewModel.desigItems)
回调函数中进行了_processFrequenciesData
调用。
但是,您没有填充viewModel.desigItems
,而是填充在_processLoadedData
回调函数中。
这可能是一个简单的错误。您可能只想将console.log(...)
移动到另一个回调中。
现在的方式是,在loadFrequencies
的响应之前处理loadData
的响应时,您将有一个空的控制台输出(如您所见)。
答案 1 :(得分:1)
observableArray
不是数组。它是包装数组的函数(!)(正如observable
不是值,而是包装值的函数)。要检索实际值,必须调用observable:
// Push frequencies on to each of the design items in the list.
var desigItems = viewModel.desigItems(); // access the underlying array
for (var i = 0; i < desigItems.length; i++) {
desigItems[i].frequency = frequencies[i];
}
viewModel.desigItems.notifySubscribers();
console.log(viewModel.desigItems());
您所做的是向observable本身添加属性,但这不会影响observable包含的值。
现在,由于我们已经更改了viewModel.desigItems
的基础值,而没有给予敲门机会注意,我们必须调用notifySubscribers()
来通知所有人观察到已发生变化。
话虽如此,我会像这样重写你的整个代码:
(function($, ko){
function ViewModel() {
var self = this;
self.errorMessages = ko.observableArray();
self.desigItems = ko.observableArray();
self.frequencies = ko.observableArray();
}
var viewModel = new ViewModel();
$(function () {
ko.applyBindings(viewModel, $('#designnation-list-container')[0]);
});
var desigsReq = $.ddcApiGet('/widget/desigs.json').done(viewModel.desigItems);
var freqsReq = $.ddcApiGet('/widget/freqs.json').done(viewModel.frequencies);
$.when(desigsReq, freqsReq).done(function (desigs, freqs) {
desigs.forEach(function (desig, i) {
desig.frequency = freqs[i];
});
}).fail(viewModel.errorMessages);
})(jQuery, ko);
这解决了代码中的两个时序问题:
以这种方式组合这两个数组是否真的有用是另一回事。我会说这不是一个非常干净的解决方案。
P.S。:你真的可以把这个问题缩短,几乎没有你发布的代码与手头的问题有任何关系。