在淘汰赛嵌套的foreach中获取dsata

时间:2016-10-16 16:26:15

标签: javascript jquery html knockout.js

我有这段代码,

<tr>
    <td></td>
    <!-- ko foreach:cols -->
    <td data-bind="html: $data "></td>
    <!-- /ko -->
</tr>
<!-- ko foreach:cells -->
<tr>
    <td data-bind="html: $index()+1 "></td>
    <!-- ko foreach: $data -->
    <td data-bind="html: '<div>' + $data[0] + '</div>' ,
         style:{ backgroundColor: '#' + $data[1] , color: '#' + $data[2] },
         attr:{id: $parent.cols()[$parent.$index()+1]}"></td>
    <!-- /ko -->
</tr>
<!-- /ko -->

我有一个cols的例子。

self.cols(["A","B","C","D"]);

错误是,

$parent.cols is not a function

我认为问题是最后一个td标记中的attr绑定。我也试过$ root.cols()[$ parent。$ index()+ 1],$ component.cols()[$ parent。$ index()+ 1]和$ data.cols()[$ parent。 $ index()+ 1]但仍然失败。

我需要使用类似“B4”之类的id来创建td,其中“B”来自self.cols()。然后“4”来自tr标记的索引。

2 个答案:

答案 0 :(得分:0)

我已经使用

解决了这个问题
<td data-bind="html: '<div>' + $data[0] + '</div>' , style:{ backgroundColor: '#' + $data[1] , color: '#' + $data[2] }, attr:{id: $parents[1].cols()[$index()] + ($parentContext.$index()+1)}"></td>

答案 1 :(得分:0)

要获得任何级别的行或列,您可以做三件事:

  • 使用绑定上下文确定位置。即$parents$index
  • 在构建视图模型时嵌入行号和列号。
  • 通过在父项和子项之间存储引用来计算视图模型中的行号和列号。

由于您只需要视图中的列和行,我认为使用第一个(就像您所做的那样)是最好的方法。如果将来你希望能够获得单元格的列和行号而不在视图中呈现它,那么你需要像这样计算的东西,放在你的表的viewmodel中:

self.getCellRowAndColumn = function(cell) {
  var colIndex = -1;
  var rowIndex = self.rows().findIndex(function(row) {
    colIndex = row.cells().indexOf(cell);
    return colIndex !== -1;
  });

  return { row: rowIndex, col: cellIndex };
};

这将允许您为包装此方法的每个单元格添加计算属性。然后你可以交换单元格和行,一切都会保持最新。

一些更一般的建议:

我强烈建议在视图和模型之间创建一个额外的可读层。任何同事,甚至 future-John-Arellano ,都难以深入挖掘$data[0]foreach: $data等数据绑定。

对于表格,这是一个自然的细分:

  • TableViewModel包含
  • RowViewModel具有行索引和单元格数组
  • CellViewModel具有内容和样式,行索引列索引

var COL_NAMES = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // support up to 26 columns

var CellViewModel = function(cellData) {
  // Model properties mapping
  this.content = ko.observable(cellData[0]);
  this.backgroundColor = ko.observable(cellData[1]);
  this.textColor = ko.observable(cellData[2]);
  
  // Extra viewmodel props
  this.styleAttr = ko.pureComputed(function() {
    return {
      backgroundColor: "#" + this.backgroundColor(),
      color: "#" + this.textColor(),
    };
  }, this);
};

CellViewModel.create = function(cellData) {
  return new CellViewModel(cellData);
};

CellViewModel.prototype.getId = function(col, row) {
  return "cell" + (row() + 1) + COL_NAMES[col()];
};

var RowViewModel = function(rowCellData) {
  this.cells = ko.observableArray(rowCellData.map(CellViewModel.create));
};

RowViewModel.create = function (rowCellData) {
  return new RowViewModel(rowCellData);
};

var TableViewModel = function(allCellData) {
  this.rows = ko.observableArray(allCellData.map(RowViewModel.create));
  
  this.cols = ko.pureComputed(function() {
    // Find row with max. cells
    var colCount = this.rows().reduce(function(max, cur) {
        return Math.max(max, cur.cells().length);
    }, 0);
    
    return COL_NAMES
      .substring(0, colCount)
      .split("");
    
  }, this);
};

// Test data
var testCellData = [
  // row 1
  [
    // col A
    [
      "Test cell 1A", // html content
      "0000FF", // background color
      "FF0000" // text color
    ],
    // col B
    [
      "Test cell 1B", // html content
      "FF0000", // background color
      "0000FF" // text color
    ]
  ],
  // row 2
  [
    // col A
    [
      "Test cell 2A", // html content
      "00FF00", // background color
      "FF0000" // text color
    ],
    // col B
    [
      "Test cell 2B", // html content
      "0000FF", // background color
      "FF0000" // text color
    ]
  ]
];

ko.applyBindings(new TableViewModel(testCellData));
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<table>
  <thead>
    <th></th>
    <!-- ko foreach: cols -->
    <th data-bind="text: $data "></th>
    <!-- /ko -->
  </thead>
  <tbody>
    <!-- ko foreach: rows -->
      <tr>
        <td data-bind="text: $index() + 1"></td>
        <!-- ko foreach: cells -->
        <td data-bind="html: content,
                       style: styleAttr,
                       attr: { id: getId($index, $parentContext.$index) }"></td>
        <!-- /ko -->
      </tr>    
    <!-- /ko -->
  </tbody>
</table>