通过knockout.js中的特定属性对项目进行排序

时间:2014-11-03 18:47:16

标签: knockout.js

我在表格中显示了一系列对象。对象的两个属性是" isGroup",一个布尔值,如果帐户是组的一部分则返回true," groupName"返回一个字符串。

我想要实现的是一个表,其中首先列出了不属于某个组的所有帐户,然后是特定组中所有帐户的逐个组列表,其中组名显示为每个街区的顶部。

我是淘汰赛的初学者,到目前为止我的表现如下:

   <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的工具,我觉得它可能很有用。

2 个答案:

答案 0 :(得分:0)

我已经尝试了一些无法看到你的具体细节的东西。首先,在viewmodel中,我创建了两个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然后一次呈现这些计算,首先在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>

希望这会有所帮助 - 如果不是,我很乐意进一步澄清是否我们可以了解更多关于您的视图模型等。

答案 1 :(得分: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的数据结构分离。模板应该基本上只对发送给它们的数据做出反应 - ViewModels如何组织/排序数据取决于ViewModel。在您的情况下,我相信模板和ViewModel数据的这种结构也将适应分组的不同排序顺序 - 因此如果“group1”应该首先出现,模板将无关紧要 - 它只会呈现“group1”html当它看到具有该值的对象时。

这有帮助吗?