我有一个下拉按钮,在ajax请求完成后应该可以使用。
<div class="form-input">
<label class="">Sort by:</label>
<select name="orderby" class="selectpicker" data-bind="value: sortBy, optionsCaption: 'Default', disable: waiting">
<option value="some_value">some_option</option>
<option value="some_value">some_option</option>
</select>
</div>
在请求的页面上,它最初加载数据
$(function() {
//Initialization
var vm = new ArticleViewModel();
initialLoadArticles(vm);
ko.applyBindings(vm, $("#article-plugin")[0]);
});
function ArticleViewModel() {
var self = this;
//options =>
this.articles = ko.observableArray([]);
this.pageSize = 12;
this.sortBy = ko.observable('asc');
this.currentPage = ko.observable(1);
this.waiting = ko.observable(true);
this.totalPages = 0;
this.initMode = true;
this.timerId = null;
this.viewTemplate = ko.observable('listview-template');
if (this.viewTemplate() === "listview-template") {
this.pageSize = 4
} else {
this.pageSize = 12
};
this.sortBy.subscribe(function(event) {
console.log(event);
self.optionChanged();
loadArticles(self);
});
this.optionChanged = function() {
this.currentPage(1);
}
this.setCardView = function() {
self.viewTemplate('cardview-template');
loadArticles(self);
}
this.setListView = function() {
self.viewTemplate('listview-template');
loadArticles(self);
}
}
function initialLoadArticles(vm) {
vm.waiting(true);
var params = {
page: vm.currentPage(),
size: vm.pageSize,
sortby: vm.sortBy()
};
api.ajax.get(api.urls.article.getArticles, params, function(response) {
console.log('waiting: ' + vm.waiting());
if (response.success) {
vm.articles(response.data.items);
vm.waiting(false);
}
});
}
好吧,在一个页面上显示所有文章,但下拉按钮仍然被阻止,我不知道究竟是什么问题。
答案 0 :(得分:2)
我建议您对viewmodel进行一些更改,通过订阅自动加载。
我认为您总是希望在加载后将waiting
设置为false,而不管请求是否成功。还要考虑低级请求错误,需要为这些错误添加处理程序。
function ArticleViewModel() {
var self = this;
self.articles = ko.observableArray();
self.pageSize = ko.observable();
self.sortBy = ko.observable('asc');
self.currentPage = ko.observable();
self.waiting = ko.observable(true);
self.viewTemplate = ko.observable();
// API
self.setCardView = function() {
self.viewTemplate('cardview-template');
self.pageSize(12);
self.currentPage(1);
};
self.setListView = function() {
self.viewTemplate('listview-template');
self.pageSize(4);
self.currentPage(1);
};
// compute Ajax-relevant parameters
self.ajaxParams = ko.pureComputed(function () {
return {
page: self.currentPage(),
size: self.pageSize(),
sortby: self.sortBy()
};
}).extend({ rateLimit: { timeout: 10, method: 'notifyWhenChangesStop' } });
// auto-load when params change
self.ajaxParams.subscribe(function (params) {
self.waiting(true);
api.ajax.get(api.urls.article.getArticles, params, function (response) {
if (response.success) {
self.articles(response.data.items);
}
self.waiting(false);
});
});
// set inital view (also triggers load)
self.setListView();
}
$(function() {
var vm = new ArticleViewModel();
ko.applyBindings(vm, $('#article-plugin')[0]);
});
更严格地说,我建议您将true
或false
作为“加载”指标。技术上可能会运行多个Ajax请求,这将是竞争条件。第一个返回的请求将重置“加载”状态,下一个请求仍会覆盖视图模型数据。使用计数器,或在有待处理请求时阻止新请求。
rateLimit
扩展程序可确保对参数进行快速连续更改,例如调用setListView()
时发生的更改,不会导致多个Ajax请求。
如果您的Ajax请求是由jQuery在内部完成的,我建议您使用以下设置来使用done
,fail
和always
承诺处理程序:
function ApiWrapper() {
var self = this;
function unwrapApiResponse(response) {
if (response.success) {
return new $.Deferred().resolve(response.data).promise();
} else {
return new $.Deferred().reject(response.error).promise();
}
}
self.getArticles = function (params) {
return $.get('articleUrl', params).then(unwrapApiResponse);
};
// more functions like this
}
var api = new ApiWrapper();
并在您的viewmodel中:
self.ajaxParams.subscribe(function (params) {
self.waiting(true);
api.getArticles(params).done(function (data) {
self.articles(data.items);
}).fail(function (err) {
// show error
}).always(function () {
self.waiting(false);
});
});