【问题标题】:cannot access parent datacontext and bind to click event无法访问父数据上下文并绑定到单击事件
【发布时间】:2014-09-09 23:09:25
【问题描述】:

即使查看了此处找到的工作示例:http://jsfiddle.net/tsenyi/FCFRE/ 我无法从 foreach 绑定访问我的数据的父上下文。我想处理订单明细表中删除按钮的点击事件。 与我类似的其他几个问题都指向了此处找到的淘汰文档中的第 2 项: http://knockoutjs.com/documentation/click-binding.html

由于我的智力有限,我无法理解上述文档为何能解决我的问题。请帮助我。

注意事项: 标题中的此按钮触发删除处理程序。它只是一个测试:

<input type="button" value="Remove = this works" data-bind="click:RemoveLineItem" />

这是损坏的按钮(这是本问题的主题)。我不尝试在这里将 $index 传递给我的处理程序。我需要这样做,但我出于调试目的删除了代码:

<td><input type="button" value="Remove - this does not work" data-bind="click: $root.RemoveLineItem"/></td>

作为记录:请注意,在文档就绪函数中我的视图模型中创建的示例数据将两个 orderDetail 对象添加到订单详细信息对象。当我从按钮中删除 data-bind 语句时,两个数据行都会被渲染。如下所示,只渲染一行。我不知道为什么我做错了什么。

jquery 版本 = 2.1.1 淘汰版 = 3.1.0

下面显示的 javascript 文件由母版页加载,因此脚本元素未显示在我的 html 中。除上述问题外,所有绑定都按预期工作。

    <form data-bind="submit:submitOrder">
<div>
    <div data-bind="with: Hdr">
        <p>ID: <input data-bind="value:ID" /></p>
        <p>Order Date: <input data-bind="value:OrderDate" /></p>
        <p>Customer Name: <input data-bind="value:CustomerName" /></p>
        <p>Customer City:<input data-bind="value:CustomerCity" /></p>

    </div>

    <input type="button" value="Remove = this works" data-bind="click:RemoveLineItem" />
    <table>
        <thead>
            <tr>
                <th>Row ID</th>
                <th>Item ID</th>
                <th>Item Desc</th>
                <th>Qty</th>
                <th>Price</th>
                <th>Ext</th>
                <th>Remove</th>
            </tr>
        </thead>

        <tbody data-bind="foreach: Dtl">
            <tr>
                <td><input data-bind="value: ID" /></td>
                <td><input data-bind="value: ItemID" /></td>
                <td><input data-bind="value: Description" /></td>
                <td><input data-bind="value: Qty" /></td>
                <td><input data-bind="value: Price" /></td>
                <td><input data-bind="value: Ext" /></td>
                <td><input type="button" value="Remove - this does not work" data-bind="click: $root.RemoveLineItem"/></td>
            </tr>
        </tbody>
    </table>

</div>
    <input type="submit" value="Submit" />
</form>

// javascript...


var today = function () {
    this.now = new Date();
    this.dd = now.getDate();
    this.mm = now.getMonth() + 1;
    this.yy = now.getFullYear();
    if (dd < 10) { dd = '0' + dd }
    if (mm < 10) { mm = '0' + mm }
    return mm + '/' + dd + '/' + yy;
}

var orderHeader = function (id, orderDate, customerName, customerCity) {
    this.ID = ko.observable(id);
    this.OrderDate = ko.observable(orderDate);
    this.CustomerName = ko.observable(customerName);
    this.CustomerCity = ko.observable(customerCity);
};

var orderDetail = function (id, orderID, itemID, description, qty, price) {
    var self = this;
    this.ID = ko.observable(id);
    this.OrderID = ko.observable(orderID);
    this.ItemID = ko.observable(itemID);
    this.Description = ko.observable(description);
    this.Qty = ko.observable(qty);
    this.Price = ko.observable(price);
    this.Ext = ko.computed(function () { return self.Qty() * self.Price() }, orderDetail);
};

// ---------------------------

var sales = function () {
    var self = this;
    self.blue = ko.observable(30);
    self.orange = ko.observable(14);
    self.pink = ko.observable(44);
    self.showPurple = ko.observable(true);
};

var viewModel = function (hdr, dtl, sales) {
    var self = this;
    self.Hdr = ko.observable(hdr);
    self.Dtl = ko.observableArray(dtl);
    self.Sales = ko.observable(sales);
    self.RemoveLineItem = function () {
        //Dtl.splice(index, 1);
        alert('RemoveLineItem was called');
    };

    self.submitOrder = function () {
        // http://stackoverflow.com/questions/16245905/fetching-or-sending-data-from-a-form-using-knockout-js
        var hdr = {
            ID: self.Hdr().ID(),
            OrderDate: self.Hdr().OrderDate(),
            CustomerName: self.Hdr().CustomerName(),
            CustomerCity: self.Hdr().CustomerCity()
        };
        $.post("/api/OrderAPI/SubmitOrderHeader", hdr, function (response) { alert('submitted'); });

    }

    self.gridViewModel = new ko.simpleGrid.viewModel({
        data: this.Dtl, columns:
            [
                { headerText: "ID", rowText: "ID", width: 230 },
                { headerText: "ItemID", rowText: "ItemID", width: 280 },
                { headerText: "Description", rowText: "Description", width: 430 }
            ]

    });
};


$(document).ready(function () {

    var orderOne = new orderHeader(1, today(), 'sam', 'manhattan beach');
    var details = [
        new orderDetail(1, 1, 10, 'laptop', 3, 2300),
        new orderDetail(2, 1, 36, 'mouse', 2, 18)
    ];
    var sls = new sales();
    //ko.applyBindings(new orderHeader(0,new Date(),'Sam','Santa Monica'));
    ko.applyBindings(viewModel(orderOne, details, sls));
});

【问题讨论】:

  • 你试过$parent而不是$root吗?看起来你想提升 1 级。 $root 一直到顶层,如果不查看所有代码,可能不是正确的上下文。
  • 谢谢,是的,我有,但它不起作用

标签: knockout.js


【解决方案1】:

我刚刚查看了您的代码。看起来不错 - 我经常使用类似的模式,其中我有一个带有项目列表的视图模型,该列表使用 foreach 呈现,并且对于每个项目我都有一个删除按钮,该按钮回调到 $parent.removeSomething功能。因此,出于信心,我将您的 HTML 和 JS 放入小提琴中并调整了几件事:

  • 我使用上面的 300 波特校正来插入新关键字
  • 我调整了您的 RemoveLineItem 函数,以显示您不需要传递 $index,而是可以利用 Knockout 提供给您的参数 - 这是 Knockout 的第 2 项中描述的技术您参考的文档。

看起来像这样:

self.RemoveLineItem = function (line_item, event) {
    self.Dtl.remove(line_item);
    alert('RemoveLineItem was called');
};

这是小提琴:

http://jsfiddle.net/RUZ4W/

所以这对我有用……对你有用吗?如果 Fiddle 确实对您有用,那么希望它可以让您确信您的代码在正确的轨道上。然后问题可能是由您的应用程序中的其他内容引起的。你有其他视图模型吗?如果这样做,您可以尝试注释掉 ko.applyBinding 语句,看看是否可以隔离导致问题的另一个视图模型。

【讨论】:

    【解决方案2】:

    尝试更改此行:

    ko.applyBindings(viewModel(orderOne, details, sls));
    

    到这一行(添加new):

    ko.applyBindings(new viewModel(orderOne, details, sls));
    

    【讨论】:

      猜你喜欢
      • 2010-11-10
      • 1970-01-01
      • 2015-07-29
      • 1970-01-01
      • 2012-12-13
      • 1970-01-01
      • 2016-04-22
      • 2013-05-04
      • 2014-06-07
      相关资源
      最近更新 更多