敲除可观察数组的值不正确

时间:2014-12-17 19:44:53

标签: javascript html5 knockout.js

我正在使用web application使用Asp.Net Mvc,其中我使用knockout Js通过对数据执行某些操作来检索并将数据发送到Html View。

例如,我在名为datainput

的数组中有以下数据
Grade Type Volume Price
A     Buy   1000   10
A     Sell  1200   10
B     Sell  100    100

我正在计算一个数组,这样当在html页面上显示时,它只需要一个不同的Grade值,并将该等级下的数据分组,如

A
Buy 1000 10
Sell 1200 10

B
Sell 100 100

使用上述功能如下

self.uniqueSelect = ko.dependentObservable(function () {
            var Transactiontypes = ko.utils.arrayMap(self.datainput(), function (item) { return item.Grade })
            return ko.utils.arrayGetDistinctValues(Transactiontypes);
        });

我不认为上面的脚本存在问题,但不确定但是我继续使用从上面的脚本中获取的数据并尝试将其填充到html,如下所示

 <!--ko foreach: uniqueSelect-->

        <tr>
            <td class="clientproductHeader" data-bind="text: $data"></td>
            <td class="clientproductHeader" colspan="10"></td>
        </tr>


        <tbody data-bind="foreach: ko.observableArray($root.datainput()).extendsdistinct('Grade').index.Grade()[$data]">
<tr>
 <script type="text/html" id="read-template">

        <td data-bind="text: Type"></td>
        <td data-bind="text: Volume"></td>
        <td  data-bind="text: (typeof Price() === 'number') ? Price().toFixed(2) : '' "></td>      

    </script>
</tr>

        </tbody>
        <!--/ko-->

    </table>

上述脚本由于某些原因显示重复数据,例如如果等级重复两次,如示例数据中那样,它会显示该等级的相同数据两次,如果重复三次,则显示三次,依此类推。 / p>

我认为错误是<!--ko foreach: uniqueSelect-->,因为它只是根据相似等级的数量来循环数据。

html页面上的

结果就像

A
    Buy 1000 10
    Sell 1200 10

B
    Sell 100 100

A
    Buy 1000 10
    Sell 1200 10

在上述数据中,A级重复两次,因此所有A级数据重复两次,因为B级只有一个条目,因此,它只发生一次 我收到的数据屏幕enter image description here 不知道如何处理这个

1 个答案:

答案 0 :(得分:1)

我经历了一个版本,它做了我认为你想要完成的事情。它使用Pēteris描述的方法。 See it in action

您希望保持视图代码尽可能简单,并且要小心重新回到$root。如果你是积极的,你想用过滤器做一个,做一个类似下面的分组,然后迭代它的每个条目/孩子。另外,尽量避免在视图中声明observable。

最后,您可以将groupByGrade()getGrades()合并到一个函数中,该函数返回一个具有每个结果的属性的对象。它会节省迭代周期。

观点:

    

<tr>
  <td class="clientproductHeader" data-bind="text: 'Grade ' + $data + ' (' + $root.log()[$data].length + ' trades)'"></td>
  <td class="clientproductHeader" colspan="10"></td>
</tr>


<tbody data-bind="foreach: $root.log()[$data]">
  <tr>
    <td data-bind="text: type"></td>
    <td data-bind="text: volume"></td>
    <td data-bind="text: (typeof price === 'number') ? price.toFixed(2) : '' "></td>
    <td class="actioncells">

      <a class="btn btn-success" title="Edit" data-bind="click: $root.edit">Edit</a>
    </td>

    <td class="actioncells">
      <a class="btn btn-danger" title="Delete " data-bind="click: $root.remove">Delete</a>
    </td>
  </tr>

</tbody>
<!--/ko-->

JavaScript:

function testViewModel() {

  // Underscore and Lo-dash both have a function to group
  // an object by key. That's what you want. Here is a
  // really simple version.
  function groupByGrade(data) {
    return data.reduce(function(last, next) {
      if (last[next.grade]) {
        last[next.grade].push(next);
      } else {
        last[next.grade] = [next];
      }
      return last;
    }, {});
  }

  // Get a unique list of the grades in the data to iterate over
  function getGrades(data) {
    return data.reduce(function(last, next) {
        return !!~last.indexOf(next.grade) ? last : last + next.grade;
    }, '').split('');
  }

  var rawData = [
    {
      grade: 'A',
      type: 'Buy',
      volume: 1000,
      price: 10
    }, {
      grade: 'A',
      type: 'Sell',
      volume: 1200,
      price: 10
    }, {
      grade: 'B',
      type: 'Sell',
      volume: 100,
      price: 100
    }
  ];

  console.log(getGrades(rawData));

  this.log    = ko.observable(groupByGrade(rawData));
  this.grades = ko.observableArray(getGrades(rawData));
}

ko.applyBindings(new testViewModel());