我尝试使用Knockout创建一个简单的电子表格。我试图让每个单元格都可观察到,因此在更改时,我可以评估该值并相应地进行计算。因此,如果他们在一个单元格中输入6 + 7,我可以评估并将值更改为总数。
但是,我不能让每个细胞都能被观察到。也许我错了。
我试图创建一个小提琴,但现在正在争取加载jquery。因此,尽管我可以在本地Visual Studio中运行它,但小提琴却在抱怨$。 (任何帮助修复都会很棒)。
http://jsfiddle.net/tr9asadp/1/
我生成我的可观察数组,如下所示: self.RowCount = ko.observable(0); self.ColumnCount = ko.observable(0);
self.Columns = ko.observableArray([]);
self.Rows = ko.observableArray([]);
self.Refresh = function () {
for (i = 0; i < self.RowCount(); i++) {
var obj = {
data: i + 1,
calculated: i,
rowNum: i,
colNum: 0,
columns: ko.observableArray([])
};
for (j = 0; j < self.ColumnCount(); j++) {
obj.columns.push(ko.observable({
label: self.Letters[j],
value: j + 1,
colIndex: j,
rowIndex: i
}));
}
self.Rows.push(obj);
}
self.ShowSheet(self.RowCount() > 0 && self.ColumnCount() > 0);
我根据用户输入的列和行渲染表格(目前,限制为5乘5,因为我使用数组将1,2,3(列)转换为A,B,C。但是这是暂时的,将被修复。
如何让每个单元格都能被观察到,以便我可以订阅并在变更时触发事件?
答案 0 :(得分:1)
您似乎没有使用cellObject
(来自您的小提琴)。如果您向行添加cellObject
类型的对象并在value
中有一个可观察对象,则可以订阅其中的更改。
固定代码:
var cellObject = function() {
var self = this;
self.data = ko.observable();
self.calculated = ko.observable();
self.rowNum = ko.observable(0);
self.colNum = ko.observable(0);
self.rows = ko.observableArray([]);
self.value = ko.observable();
}
function SpreadsheetViewModel() {
var self = this;
self.ShowSheet = ko.observable(false);
self.ShowSheet(false);
self.Letters = ['A', 'B', 'C', 'D', 'E']
self.RowCount = ko.observable(0);
self.ColumnCount = ko.observable(0);
self.Columns = ko.observableArray([]);
self.Rows = ko.observableArray([]);
function valueChanged(newValue) {
console.log("Value changed to " + newValue);
}
self.Refresh = function() {
for (i = 0; i < self.RowCount(); i++) {
var row = {
cells: ko.observableArray([])
};
for (j = 0; j < self.ColumnCount(); j++) {
var cell = new cellObject();
cell.label = self.Letters[j];
cell.data(i + 1);
cell.calculated(i);
cell.rowNum(i);
cell.colNum(j);
cell.value(j + 1);
cell.value.subscribe(valueChanged);
row.cells.push(cell);
}
self.Rows.push(row);
}
self.ShowSheet(self.RowCount() > 0 && self.ColumnCount() > 0);
}
self.Refresh();
}
var vm = new SpreadsheetViewModel();
ko.applyBindings(vm);
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<div id="spreadsheetSection">
<div class="row">
<div class="col-xs-3 text-right">No. of Columns</div>
<div class="col-xs-2">
<input type="text" class="form-control" placeholder="Columns" data-bind="value: ColumnCount">
</div>
<div class="col-xs-3 text-right">No. of Rows</div>
<div class="col-xs-2">
<input type="text" class="form-control" placeholder="Rows" data-bind="value: RowCount">
</div>
<div class="col-xs-2">
<button class="btn btn-default" data-bind="click: Refresh">Refresh</button>
</div>
</div>
<div class="row">
<!-- ko if: ShowSheet -->
<table class="table table-bordered table-hover table-striped">
<tbody>
<tr data-bind="foreach: Rows()[0].cells">
<td>
<span data-bind="text: label"></span>
</td>
</tr>
</tbody>
<tbody data-bind="foreach: Rows">
<tr data-bind="foreach: cells">
<td>
<input type="text" class="form-control" data-bind="value: value">
</td>
</tr>
</tbody>
</table>
<!-- /ko -->
</div>
</div>
答案 1 :(得分:0)
我使用了一个writableComputable http://knockoutjs.com/documentation/computed-writable.html,这样如果你在其中一个单元格中输入1 + 1并标签,它将变为2.这里是更新的小提琴。 http://jsfiddle.net/tr9asadp/5/
function column(label, value, colIndex, rowIndex ){
var self = this;
this.label = ko.observable(label);
this.value = ko.observable(value);
this.colIndex = ko.observable(colIndex);
this.rowIndex = ko.observable(rowIndex);
this.writableValue = ko.pureComputed({
read: function () {
return self.value();
},
write: function (v) {
self.value(eval(v))
},
owner: this
});
}