我使用SPServices和KnockoutJS在页面上加载一些数据,特别是项目列表和每个项目的任务数。
我稍微简化了示例,但我遇到的问题是获取ajax调用异步的值。我通过使用jQuery绑定结果而不是返回任何内容来廉价地解决它:
function ProjectModel(title, id) {
var self = this;
self.id = id;
self.title = title;
self.tasks = ko.computed(function() {
$().SPServices({
operation: "GetListItems",
async: true,
webURL: "/projects/" + self.id,
listName: "Tasks",
CAMLQuery: // query..,
CAMLViewFields: "<ViewFields><FieldRef Name='ID' /></ViewFields>",
completefunc: function (xData, Status) {
$(".tasks-" + id).text($(xData.responseXML).SPFilterNode("z:row").length);
}
});
});
}
我看了一下这些网站 Async dependantobservables async computed observables
这是要走的路吗? 编辑:
好了所以更多的代码(在这里删除了一些东西):
function onGetProjectsCompleted(projects) {
var projectViewModel = new ProjectViewModel();
projectViewModel.init(projects);
ko.applyBindings(projectViewModel);
}
function beforeLoadingProjects() {
$(".loadingMessage").show();
}
function initProjectsView() {
ProjectsRepository.getOpenProjects(beforeLoadingProjects, onGetProjectsCompleted);
}
function ProjectViewModel() {
var self = this;
self.openProjects = ko.observableArray();
self.init = function initProjectViewModel(projects) {
$.each(projects, function() {
self.openProjects.push(this);
});
});
};
}
var ProjectsRepository = {
getOpenProjects: function (beforeComplete, onComplete) {
var options = {
operation: "GetListItems",
completefunc: function(xData, status) {
var projects = new Array();
$(xData.responseXML).SPFilterNode("z:row").each(function() {
var item = $(this);
projects.push(new ProjectModel(
item.attr("ows_Title"),
item.attr("ows_ProjectID")
));
});
onComplete(projects);
}
};
beforeComplete();
$().SPServices(options);
}
};
请注意,我不想列出每个项目的任务,我只想拥有一个属性,其中包含每个项目的任务数,即没有数组。
再次感谢。
答案 0 :(得分:1)
我无法告诉您如何使用上面的类(模型),但@anders是正确的:您的模型不应该直接操作DOM元素......这就是Knockout&#39;视图绑定用于...
试试这个(披露:我没有在现场环境中测试这个):
function ProjectModel(title, id) {
var self = this;
self.id = id;
self.title = title;
self.tasks = ko.observable(0);
$().SPServices({
operation: "GetListItems",
async: true,
webURL: "/projects/" + self.id,
listName: "Tasks",
CAMLQuery: // query..,
CAMLViewFields: "<ViewFields><FieldRef Name='ID' /></ViewFields>",
completefunc: function (xData, Status) {
if (Status !== "success") {
alert("failed to get tasks! Ajax call error.");
return;
}
self.tasks(
$(xData.responseXML).SPFilterNode("rs:data").attr('ItemCount')
);
}
});
}
<div id="mytemplate">
<h2>
<span data-bind="text: title"></span> Project has
<span data-bind="text: tasks"></span> Tasks
</h2>
</div>
ko.applyBindings(
new ProjectModel("your project title", "your project ID"),
document.getElementById("mytemplate")
);
尝试使用上面的内容并查看是否获得输出...任务数量最初为零,但如果您的任务列表有效且任务在那里,那么一旦查询完成,它将自动更新。
答案 1 :(得分:0)
我之前没有使用过SPServices,但我首先要通过创建服务对象将模型与ajax调用分开。
然后传入observable来填充像
这样的东西var ajaxServices = (function(){
return {
getProjectTasks: getProjectTasks
};
function getProjectTasks(projectId, tasksObservable){
$().SPServices({
operation: "GetListItems",
async: true,
webURL: "/projects/" + projectId,
listName: "Tasks",
CAMLQuery: // query..,
CAMLViewFields: "<ViewFields><FieldRef Name='ID' /></ViewFields>",
completefunc: function (xData, Status) {
tasksObservable(xData);
});
}
})();
function ProjectModel(title, id) {
var self = this;
self.id = id;
self.title = title;
self.tasks = ko.observableArray([]);
self.getTasks = function (){
ajaxServices.getProjectsTasks(sif.id, self.tasks);
};
}