阵列内的Knockout数组

时间:2017-08-10 02:06:31

标签: javascript jquery arrays knockout.js

我尝试使用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。但是这是暂时的,将被修复。

如何让每个单元格都能被观察到,以便我可以订阅并在变更时触发事件?

2 个答案:

答案 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>

修正小提琴:https://jsfiddle.net/tr9asadp/3/

答案 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
    });
}