2014-11-03 47 views
0

我有一系列的对象被显示在一个表中。对象的两个属性是“isGroup”,一个布尔值,如果该帐户是组的一部分则返回true,而“groupName”返回一个字符串。按特定属性对项目进行排序knockout.js

我试图实现的是一个表,它列出了第一个不属于组的组成部分的所有帐户,后面跟着特定组中所有帐户的组列表,其中组名列出一次在每个块的顶部。

我是一个淘汰赛初学者,我到目前为止是这样的:

<tbody data-bind="foreach: dashboard.widgets.modelPortfolio.models"> 
     <!-- ko if: isGroup === false --> 
     <tr data-bind="if: isGroup === false"> 
      <td class="labelCol"><span data-bind="text: accountName"></span></td> 
      <td class="col"><span data-bind="text: modelName"></span></td> 
      <td class="col"><span data-bind="text: driftPercentage"></span></td> 
     </tr> 
     <!-- /ko--> 
     <!-- ko if: isGroup === true --> 
     <tr> 
      <td class="labelCol"><b><span data-bind="text: groupName"></span></b></td> 
      <td class="col"><span data-bind="text: modelName"></span></td> 
      <td class="col"><span data-bind="text: driftPercentage"></span></td> 
     </tr> 
     <tr> 
      <td class="labelCol"><b><span data-bind="text: accountName"></span></b></td> 
      <td class="col"></td> 
      <td class="col"></td> 
     </tr> 
     <!-- /ko --> 
    </tbody> 

它显示这是一组的一部分,每个账户上面的组名的标题,所以我的问题是:

1)让它每个组只显示一次,并且 2)让属于每个组的所有帐户都显示在该组下。

没有可能的组数。 从我的研究到目前为止,我已经看到一个名为arrayGetDistinctValues的util,我认为它可能有用。

+0

你可以发布你的视图模型代码,以帮助理解多一点?我觉得应该可以使用一个或两个[Computed Observables](http://knockoutjs.com/documentation/computedObservables.html) – 2014-11-03 19:21:14

回答

0

我已经刺了一些应该工作而不能看到你的具体细节。首先,在视图模型中,我创建了两个computed observables。通过对象的第一个循环(我假定它是在一个名为obj的可观察数组中)。它返回一个包含不在一个组中的对象的新数组。第二个构建另一个键/值对的数组,其中键是groupName,值是包含该组中对象的另一个数组。

我假设(再次没有看到您的viewmodel细节)modelName和driftPercentage在组中的所有对象中都是通用的,并且将仅使用第一个对象中的值来填充组的值。

var vm = { 
    ungrouped: ko.computed(function() { 
     var ret = []; 
     for (var x = 0; x < obj().length; x++) { 
      if (!obj()[x].isGroup) 
       ret.push(obj()[x]); 
     } 
     return ret; 
    }), 

    grouped: ko.computed(function() { 
     var ret = []; 
     function getGroup(groupName, modelName, driftPercentage) { 
      for (var x = 0; x < ret.length; ret++) { 
       if (ret[x].groupName == groupName) 
        return ret[x]; 
      } 
      var g = { 
       groupName: groupName, 
       modelName: modelName, 
       driftPercentage: driftPercentage, 
       objects: [] 
      } 
      ret.push(g); 
      return g; 
     } 

     for (var x = 0; x < obj().length; x++) { 
      if (obj()[x].isGroup) { 
       var g = getGroup(obj()[x].groupName, obj()[x].modelName, obj()[x].driftPercentage); 
       g.objects.push(obj()[x]); 
      } 
     } 
     return ret; 
    }) 
} 

的HTML然后使得这些computeds一次一个,第一上循环ungrouped,然后经grouped。虽然遍历grouped,它随后还循环该组中的对象的子阵列上:

<tbody data-bind="foreach: dashboard.widgets.modelPortfolio.models"> 
    <!-- ko foreach: ungrouped --> 
    <tr> 
     <td class="labelCol"><span data-bind="text: accountName"></span></td> 
     <td class="col"><span data-bind="text: modelName"></span></td> 
     <td class="col"><span data-bind="text: driftPercentage"></span></td> 
    </tr> 
    <!-- /ko--> 
    <!-- ko foreach: grouped --> 
    <tr> 
     <td class="labelCol"><b><span data-bind="text: groupName"></span></b></td> 
     <td class="col"><span data-bind="text: modelName"></span></td> 
     <td class="col"><span data-bind="text: driftPercentage"></span></td> 
    </tr> 
     <!-- ko foreach: objects --> 
     <tr> 
      <td class="labelCol"><b><span data-bind="text: accountName"></span></b></td> 
      <td class="col"></td> 
      <td class="col"></td> 
     </tr> 
     <!-- /ko --> 
    <!-- /ko --> 
</tbody> 

希望这将帮助 - 如果不是我很高兴能进一步明确,如果我们能更多地了解您的视图模型等。

0

有几种方法可以从您的视图模型中处理此问题。看看你的模板,我将推断出特定组的“标题”行是由视图模型上的某些内容定义的。

因此,我会这样做的方式是将每行视为集合中的实体(可观察数组或返回数组的计算函数)。这样,演示文稿与您的小组的排序脱钩。在此之上,对表格中的行您的根对象(由foreach<table>标签来定义的)应该是一个复杂的对象:

this.groups = ko.computed(function() { 
    return [ 
     { 
      name: "group1", 
      entities: [ /* .... your model objects */ ] 
     }, 
     { 
      name: "noGroup", 
      entities: [ /* .... your model objects */ ] 
     } 
}); 

然后,你可以有你的模板通过组迭代,并确定演示基于该name属性:

<tbody data-bind="foreach: groups"> 
    <!-- ko if: name === "group1 --> 
     <tr> 
      <td class="labelCol"><b><span data-bind="text: groupName"></span></b></td> 
      <td class="col"><span data-bind="text: modelName"></span></td> 
      <td class="col"><span data-bind="text: driftPercentage"></span></td> 
     </tr> 

     <!-- ko foreach: entities --> 
      <tr data-bind="if: isGroup === false"> 
       <td class="labelCol"><span data-bind="text: accountName"></span></td> 
       <td class="col"><span data-bind="text: modelName"></span></td> 
       <td class="col"><span data-bind="text: driftPercentage"></span></td> 
      </tr> 
     <!-- /ko --> 
    <!-- /ko--> 

    <!-- ko if: name === "noGroup" --> 
     <tr data-bind="if: isGroup === false"> 
      <td class="labelCol"><span data-bind="text: accountName"></span></td> 
      <td class="col"><span data-bind="text: modelName"></span></td> 
      <td class="col"><span data-bind="text: driftPercentage"></span></td> 
     </tr> 
    <!-- /ko --> 
</tbody> 

所以这导致有你的视图模型的属性添加一些元数据,以它来帮助与模板布局你的HTML。这样做的一个好处是,它有助于将演示与ViewModel的数据结构分离。模板应该基本上只对发送给它们的数据作出反应 - ViewModel如何组织/排序数据取决于ViewModel。在你的情况下,我相信这个模板和ViewModel的数据结构也将适应不同的排序顺序 - 所以如果“group1”应该优先,模板不会在意 - 它只会渲染“group1”html当它看到一个具有该值的对象时。

这有帮助吗?

相关问题