我正在使用非常漂亮的KnockoutJS库创建一个应用程序,但是遇到了麻烦。在html页面上,我有一个普通的<select>控件,该控件要加载从Web服务返回的JSON数据。

我将可观察数组定义如下:

var laborRow = function () {
    this.positions = ko.observableArray([]);
};

页面加载时,将进行ajax调用并返回数据。在回调中,我执行以下操作:
    success: function (msg) {
        laborRow.positions = msg;
    }

基于KO文档,我希望我将结果设置为:
laborRow.positions(msg);

但是,这只是抛出一个错误,指出“laborRow.positions in not a function”

html中的模板如下:

<tbody data-bind='template: {name: "laborRowTemplate", foreach: laborLine}'> </tbody>
</div>
  <script type="text/html" id="laborRowTemplate">
        <tr>

          <td><select data-bind='options: positions, optionsText: "Title", optionsCaption: "select", value: selectedPosition '></select></td>

        </tr>
    </script>
laborRow对象是绑定(bind)到页面的ViewModel上的属性。无论出于何种原因,这都不起作用。要增加另一个皱纹,如果我添加代码以窥视observableArray并打印出一些数据,则数据就在其中。因此,它正在成功加载。

任何想法将不胜感激。

我的示例案例的完整代码:
var laborRow = function () {
    this.positions = ko.observableArray([]);
};

var projectEstimate = function () {
    this.laborLine = ko.observableArray([new laborRow()]);

};

var projectViewModel = new projectEstimate();
ko.applyBindings(projectViewModel);

//and the code in the callback function on ajax success

 success: function (msg) {
                laborRow.positions = msg;
                //laborRow.positions(msg); **this does not work - error is laborRow.positions is not a function**
            },

和html:

 <tbody data-bind='template: {name: "laborRowTemplate", foreach:
laborLine}'> </tbody>

  <script type="text/html" id="laborRowTemplate">
        <tr>
          <td><select data-bind='options: positions, optionsText:
"Title",  optionsCaption: "select", value: selectedPosition '></
select></td>

        </tr>
    </script>

最后,由于以下Sean的评论,我可以通过如下修改回调中的代码来使其工作:
success: function (msg) {
    projectViewModel.laborLine()[(projectViewModel.laborLine().length-1)].positionList(msg);
}

最佳答案

问题是您实际上尚未创建模型:

var laborRow = function () {
    this.positions = ko.observableArray([]);
    // will only be called if you call var some_var = new laborRow()
};

将函数更改为裸对象(如Knockout docs所示):
var laborRow = {
    positions: ko.observableArray([])
};

您将可以调用laborRow.positions(msg);并使它工作。

编辑

根据新代码,laborRow仍未实例化-如果您在代码中的其他位置(也许在ajax请求附近)设置var laborRow,则需要确保调用堆栈如下所示:
projectViewModel.laborLine()[0].positions()
// This will return the array you're looking for.
// The key is that laborLine is a `getter` not an attribute

我在某些场合被“ko变量是getters而不是attributes”错误咬伤了……您的代码可能会发生这种情况吗?

10-07 14:24