无法处理绑定“event:function(){return {change:flagSalesOrderItemAsEdited}}”

时间:2016-03-02 10:42:26

标签: asp.net-mvc knockout.js

我目前正在进行关于Knockout和MVC的Pluralsight课程(称为EF,MVC,Knockout,Ajax和Validation的父子数据),我对此印象非常深刻,但突然间我得到了迄今为​​止的这个bug对我来说是一个表演的限制。 这不仅是我的代码中的一个问题,它也是从Pluralsight下载的代码中的一个错误,我看到他们正在制作他们的视频! 所以在编辑部分视图中我有:

<h2>@ViewBag.Title</h2>

<p data-bind="text: MessageToClient"></p>

<div>
    <div class="form-group">
        <label class="control-label" for="CustomerName">Customer Name:</label>
        <input class="form-control" name="CustomerName" id="CustomerName"
               data-bind="value: CustomerName, event: {change: flagSalesOrderAsEdited}"/>
    </div>
    <div class="form-group">
        <label class="control-label" for="PONumber">P.O. Number:</label>
        <input class="form-control" name="PONumber" id="PONumber"
               data-bind="value: PONumber, event: {change: flagSalesOrderAsEdited}"/>
    </div>
</div>
<table class="table table-stripe">
    <tr>
        <th>Product Code</th>
        <th>Quantity</th>
        <th>Unit Price</th>
        <th><button data-bind="click: addSalesOrderItem" class="btn btn-info btn-xs">Add</button></th>
    </tr>
    <tbody data-bind="foreach: SalesOrderItems">
        <tr>
            <td class="form-group">
                <input class="form-control input-sm"
                    data-bind="value: ProductCode, event: {change: flagSalesOrderItemAsEdited}, hasfocus: true" />
            </td>
            <td class="form-group">
                <input class="form-control input-sm"
                       data-bind="value: Quantity, event: {change: flagSalesOrderItemAsEdited}" />
            </td>
            <td class="form-group">
                <input class="form-control input-sm"
                       data-bind="value: UnitPrice, event: {change: flagSalesOrderItemAsEdited}" />
            </td>
            <td class="form-group">Delete</td>
        </tr>
    </tbody>
</table>
<p><button data-bind="click: save" class="btn btn-primary">Save</button></p>
<p>
    <a href="/" class="btn btn-default btn-sm">&laquo; Back to List</a>
</p>

我申请了绑定;

<script type="text/javascript">
    var salesOrderViewModel = new SalesOrderViewModel(@Html.Raw(data));
    ko.applyBindings(salesOrderViewModel);
</script>

在我的javascript文件中我有

var ObjectState = {
    Unchanged: 0,
    Added: 1,
    Modified: 2,
    Deleted: 3
};

var salesOrderItemMapping = {
    'SalesOrderItems': {
        key: function(salesOrderItem) {
            return ko.utils.unwrapObservable(salesOrderItem.salesOrderItemId);
        },
        create: function(options) {
            return new SalesOrderViewModel(options.data);
        }
    }
};

SalesOrderItemViewModel = function(data) {
    var self = this;
    ko.mapping.fromJS(data, salesOrderItemMapping, self);

    self.flagSalesOrderItemAsEdited = function() {
        if (self.ObjectState() !== ObjectState.Added) {
            self.ObjectState(ObjectState.Modified);
        }

        return true;
    };
}

SalesOrderViewModel = function (data) {
    var self = this;
    ko.mapping.fromJS(data, salesOrderItemMapping, self);

    self.save = function() {
        $.ajax({
            url: "/Sales/Save",
            type: "POST",
            data: ko.toJSON(self),
            contentType: "application/json",
            success: function (data) {
                if (data.salesOrderViewModel !== null) {
                    ko.mapping.fromJS(data.salesOrderViewModel, {}, self);
                }

                if (data.newLocation !== undefined && data.newLocation !== null) {
                    window.location.href = data.newLocation;
                }
            }

        });
    }

    self.flagSalesOrderAsEdited = function () {
        if (self.ObjectState() !== ObjectState.Added) {
            self.ObjectState(ObjectState.Modified);
        }

        return true;
    }

映射是从服务器端viewModels派生的:

namespace SolutionName.Web.ViewModels
{
    public class SalesOrderViewModel : IObjectWithState
    {
        public SalesOrderViewModel()
        {
            this.SalesOrderItems = new ListStack<SalesOrderItemViewModel>();
        }

        public int SalesOrderId { get; set; }
        public string CustomerName { get; set; }
        public string PONumber { get; set; }
        public string MessageToClient { get; set; }
        public ObjectState ObjectState { get; set; }
        public List<SalesOrderItemViewModel> SalesOrderItems { get; set; } 
    }
}

namespace SolutionName.Web.ViewModels
{
    public class SalesOrderItemViewModel : IObjectWithState
    {
        public int SalesOrderItemId { get; set; }
        public string ProductCode { get; set; }
        public int Quantity { get; set; }
        public decimal UnitPrice { get; set; }
        public int SalesOrderId { get; set; }
        public ObjectState ObjectState { get; set; }
    }
}

错误发生在我将数据绑定到标志字段的表中:

<td class="form-group">
                <input class="form-control input-sm"
                    data-bind="value: ProductCode, event: {change: flagSalesOrderItemAsEdited}, hasfocus: true" />
            </td>

我得到'flagSalesOrderItemAsEdited'是未定义的 它落在淘汰赛剧本中。

Unable to process binding "foreach: function(){return SalesOrderItems }"
Message: Unable to process binding "event: function(){return {change:flagSalesOrderItemAsEdited} }"
Message: 'flagSalesOrderItemAsEdited' is undefined

ex.message = "Unable to process binding \"" + bindingKey + ": " + bindings[bindingKey] + "\"\nMessage: " + ex.message;

第3326行例外

那么我该如何解决这个问题呢?

EDIT 一个建议的解决方案是使用$ parent作为HTML中的前缀。 所以我试过了:

    <td class="form-group">
        <input class="form-control input-sm"
               data-bind="value: ProductCode, event: {change: $parent.flagSalesOrderItemAsEdited}, hasfocus: true" />
    </td>
    <td class="form-group">
        <input class="form-control input-sm"
               data-bind="value: Quantity, event: {change: $parent.flagSalesOrderItemAsEdited}" />
    </td>
    <td class="form-group">
        <input class="form-control input-sm"
               data-bind="value: UnitPrice, event: {change: $parent.flagSalesOrderItemAsEdited}" />
    </td>

这停止了抛出的异常。但是方法:

self.flagSalesOrderAsEdited = function () {
    if (self.ObjectState() !== ObjectState.Added) {
        self.ObjectState(ObjectState.Modified);
    }

未被调用。好像它所在的课程没有被实例化。

1 个答案:

答案 0 :(得分:1)

尝试以下内容。在循环中调用函数时使用$root

<td class="form-group">
            <input class="form-control input-sm"
                data-bind="value: ProductCode, event: {change: $root.flagSalesOrderItemAsEdited}, hasfocus: true" />
</td>

我们也可以使用$parent,这是当前背景之外的立即。 有关binding context

的更多信息