我有这段代码,
<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标记的索引。
答案 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>