0

我正在使用 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);  
                        }
              });       
        });
}

我查看了这些站点 Asyncdependentobservables 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);
        }
    };

请注意,我不想列出每个项目的任务,我只想拥有一个包含每个项目的任务数的属性,即没有数组。

再次感谢。

4

2 回答 2

1

我不知道你是如何尝试使用上面的类(模型),但@anders 是正确的:你的模型不应该直接操作 DOM 元素......这就是 Knockout 的视图绑定的用途......

试试这个(披露:我没有在现场环境中测试这个):

模型:

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")
);

尝试使用上面的方法,看看你是否得到输出......任务数最初为零,但如果你的任务列表有效并且任务在那里,那么一旦查询完成,它就会自行更新。

于 2014-08-04T23:59:28.883 回答
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);
  };    
}
于 2014-08-04T07:43:59.400 回答