【问题标题】:Why does adding a computed to an observableArray fail?为什么将计算结果添加到 observableArray 会失败?
【发布时间】:2013-10-07 10:25:13
【问题描述】:

我认为这里有些地方很不对劲。我想像这样将ko.computed 添加到ko.observableArray

在此之前我的模型是为了清晰

//var job = @Html.Raw(Json.Encode(Model.job));
//var customer = @Html.Raw(Json.Encode(Model.customer));
//var estimateMaterials = @Html.Raw(Json.Encode(Model.estimateMaterials));
//var estimate = @Html.Raw(Json.Encode(Model.estimate));
var estimateTasks = @Html.Raw(Json.Encode(Model.Tasks));

var JobPostViewModel = function(){
    var self = this;
    //self.customer = ko.observable(customer);
    //self.job = ko.observable(job);
    //self.estimateMaterials = ko.observableArray(estimateMaterials);
    //self.estimate = ko.observable(estimate);
    self.estimateTasks = ko.observableArray(estimateTasks);
    self.estimateTasks().estLaborSubTotal = ko.computed(function () {
        return (isNaN(self.EstHr)? 0: +self.EstHr) * (isNaN(self.TaskPerHourCost)? 0: +self.TaskPerHourCost);
    });
};
var model = new JobPostViewModel();
ko.applyBindings(model,  document.getElementById("my_job_form"));

这就是我的模型绑定。 my_job_formdata-bind="with:jobs",我在绑定到 estimateTasks 的表单中填充了一个表格。标记是

<tbody data-bind="foreach: $root.estimateTasks">
    <tr>
        <td>
            <input type="text" data-bind="value: EstHr" />
            <input type="hidden" data-bind="value: TaskPerHourCost" />
        </td>
        <td>
            <input type="text" data-bind="value: estLaborSubTotal" disabled />
        </td>
    </tr>
</tbody>

绑定时出现错误

ReferenceError: estLaborSubTotal 未定义

我在这里做错了什么?

【问题讨论】:

  • 查看我发布的答案,我认为阅读和理解会更简单一些。

标签: knockout.js knockout-mapping-plugin


【解决方案1】:

您正在向数组添加一个计算值。这个数组只是estimateTasks observableArray()的求值结果;

如果我理解你想要做什么。

你最好这样做。 这将向项目添加一个名为 estLaborSubTotal 的计算值。

var JobPostViewModel = function(){
    var self = this;
    ko.utils.arrayForEach(estimateTasks, function(et) {
        et.estLaborSubTotal  = ko.computed({
            read: function(){
                var estHr = this.EstHr();
                var taskPerHourCost =  this.TaskPerHourCost();
                if(estHr === null)
                    return 0;
                return estHr * taskPerHourCost; 
            },
            owner : et // specify the "this" during evaluation 
        });
    });

    self.estimateTasks = ko.observableArray(estimateTasks);
};

See fiddle

希望对你有帮助。

【讨论】:

  • 没有帮助我,// specify the "this" during evaluation 是什么意思
  • @naveen 你到底想做什么?请给knockoutjs.com/documentation/computedObservables.html
  • 我正在从 javascript 数组创建一个可观察数组。和该数组中的 foreach 元素,我正在尝试添加一个新的ko.computed
  • 这正是我的代码所做的。但我只是在创建 observable 数组之前在每个项目上添加计算。
  • 这就是我猜它不起作用的原因。您正在将 ko.computed 添加到 javascript 数组中并使整个事情 ko.observable 再次
【解决方案2】:

我认为这就是你想要做的 -

function jobPostEstimateTaskModel (task) {
    var self = this;
    // Make some properties of this task observable
    self.name = ko.observable(task.name);
    // Make a computed for each task
    self.estLaborSubTotal = ko.computed(function () {
        return (isNaN(self.EstHr)? 0: +self.EstHr) * (isNaN(self.TaskPerHourCost)? 0: +self.TaskPerHourCost);
    });
}

var JobPostViewModel = function(){
    var self = this;
    self.estimateTasks = ko.observableArray();
    $.each(estimateTasks, function (index, item) {
        self.estimateTasks.push(new jobPostEstimateTaskModel(item));
    }
};

这将遍历您创建的estimateTasks 普通旧JavaScript 数组,并为数组中的每个任务添加一个新的jobPostEstimateTaskModel 对象。它将在任务上创建可观察的属性,例如本例中的名称,然后为数组中的 每个 项创建一个计算对象。

通过以上述方式调用它,您只是在 observableArray 上创建了一个计算对象,而不是按照您的意图进行操作。

其中一个混淆点是,您的 ViewModel 有一个名为estimateTasks 的 observableArray 对象,但您在上下文“上方”还有一个变量,它的名称完全相同。考虑将您的不可观察重命名为类似 estimateTasksJson 的名称。

编辑

解决此问题的另一种方法是使用原型设计 - 您仍然需要实例化一个对象,例如 jobPostEstimateTaskModel 或任何您想调用的对象,但您可以将一个可观察对象扩展到每个实例,而不必每次都遍历该代码并添加它在模型中。

【讨论】:

  • 没有用。没有发生双向绑定。 httpPost 没有可观察的对象
  • 这实际上工作得很好,就像 Damien 的回答一样,你只是没有在小提琴或其他任何东西中显示你的代码,我们不能让你正确使用它:)
  • 老兄,我不在。我看到您在同一问题上发布的另一个答案。感谢您花时间为我服务。
  • 没问题,很高兴它有帮助
【解决方案3】:

您的问题是 foreach 内部的当前绑定内容是当前数组元素。
而且这个元素没有estLaborSubTotal属性。
您可以改用&lt;input type="text" data-bind="value: $root.estimateTasks().estLaborSubTotal" disabled /&gt;

或者你可以改变你的视图模型:

var JobPostViewModel = function(){
    var self = this;
    //self.customer = ko.observable(customer);
    //self.job = ko.observable(job);
    //self.estimateMaterials = ko.observableArray(estimateMaterials);
    //self.estimate = ko.observable(estimate);
    self.estimateTasks = ko.observableArray(estimateTasks);
    self.estLaborSubTotal = ko.computed(function () {
        return (isNaN(self.EstHr)? 0: +self.EstHr) * (isNaN(self.TaskPerHourCost)? 0: +self.TaskPerHourCost);
    });
};

并使用&lt;input type="text" data-bind="value: $root.estLaborSubTotal" disabled /&gt;

【讨论】:

  • 同意。但是在发布到服务器时如何将其绑定回来?这让我很困扰。在var estTasks= []; 会怎么样
  • 在您的 json 回传到服务器的哪个位置应该放置 estLaborSubTotal?它应该在estimateTasks 数组中吗?
猜你喜欢
  • 2016-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多