2013-10-01 46 views
0

由于数据通过AJAX加载,我需要在数据到达时更新数据。Ko.computed功能更新两次

在页面加载时,我收集数据库中的项目。然后根据所选项目(self.SelectedProject)加载任务和标签的数据。

self.Projects = ko.observableArray(); 
self.Tasks = ko.observableArray(); 
self.Tags = ko.observableArray(); 
self.SelectedProject = ko.observable(); // Chosen Project-object... 

有关初始化我加载的第一个项目数据:

self.SelectedProject(self.Projects()[0]);   // Choose first returned Project... 

然后我去填充我的标签 - 帮助阵列:

ko.computed(function() { 
    // must be ko.computed as else will not update when data arrives for Tags and Tasks (which are likely to be empty at load time)... 

    // Empty projectAvailableTags before refill... 
    self.SelectedProject().projectAvailableTags([]); 

    // First populate current project's "projectAvailableTags"-array with values... 
    for (var j = 0, jlen = self.Tags().length; j < jlen; j++) { 
     self.SelectedProject().projectAvailableTags().push(self.Tags()[j].TagName()); 
    } 

    for (var i = 0, ilen = self.Tasks().length; i < ilen; i++) { 
     //---- Populate each TaskTag-array with Tags... 
     for (var j = 0, jlen = self.Tags().length; j < jlen; j++) { 
      if (self.Tags()[j].TagTaskId() === self.Tasks()[i].TaskId) { 
       self.Task()[i].TaskTags.push(self.Tags()[j]); 
       // Populate the different tag-Arrays... 
       var tagtype = self.Tags()[j].TagType; 
       switch (tagtype()) { 
        case 0: self.Tasks()[i].Location().push(self.Tags()[j].TagName()); break; 
        case 1: self.Tasks()[i].Manager().push(self.Tags()[j].TagName()); break; 
        case 2: self.Tasks()[i].Employee().push(self.Tags()[j].TagName()); break; 

       } 
      } 
     } 

    }; 
}); 

这可能看起来很奇怪,也许我我做这个不必要的复杂。 我使用http://aehlke.github.com/tag-it/作为标记管理器,它只需要一个包含TagNames的数组。因此我没有想到如何直接使用Tags() - 数组,虽然我喜欢这样。

任务在手风琴介绍,我想在内容面板要应用的任务标签,而我用我的项目标签为tagSource为自动完成的功能...

但我不能弄清楚为什么我的标签在ko.computed上应用了2次,除非我没有它重新选择项目。

回答

1

我认为你有点失去了计算的观察点。计算可观测量与常规函数之间唯一真正的区别在于,您可以将其绑定到计算的可观察值,并在其组件更改时随时自动更新。

example in the knockout documentation用于计算观测使用/姓,这是一个很好的例子。

基于此,更新自身计算的依赖关系并不是一个好主意。在早期版本的淘汰赛中,这实际上会创建一个无限循环引用。

我假设所计算的运行两次,因为标签和任务都接收新数据,这是触发更新(但是只有一个是因为内置于敲除的保障更新)。

更好的选择是订阅SelectedProject。然后每次可观察到的变化,您都可以重新安装所有阵列。

self.SelectedProject.subscribe(function(newValue) { 
    <load your arrays here> 
}); 
+0

感谢您解决这个问题。 我仍然有一个问题,因为“SelectedProject.subscribe”不会触发当我第一次实例化我的ViewModel,会吗? 我需要以某种方式让我的for循环的AJAX运行后已返回值的任务和标签。因为现在我使用订阅功能更新这些数据,但在选择新项目之前我还需要这些数组。 –

+0

我将抽象阵列加载逻辑到一个单独的方法,然后把它用于SelectedProject.subscribe和也在回调为您的AJAX请求。 – Jared

+0

谢谢Jared! 予先得到以$ .getJSON( “/为myService/GetAllTag”, “专案编号=” + tp.ProjectId,函数(ALLDATA){/ *映射结果的标签阵列* /}的标记(对于给定的项目) 然后任务相同的方式 您是否还会在标记的回调中调用任务的getJSON? 我需要为数组加载逻辑的标记和任务我是否理解您应该这样做: $。getJSON(“/ myService/GetAllTag”,“projectid =”+ tp.ProjectId,function(adata){mapTags(); $ .getJSON(“/ myService/GetAllTask​​s”,“projectid =”+ tp.ProjectId,function(bdata ){mapTasks(); loadArray(); }) –