【问题标题】:Durandal / Knockout nested dropdowns in tableDurandal / Knockout 表格中的嵌套下拉列表
【发布时间】:2013-04-07 17:21:50
【问题描述】:

我对 Durandal 和 Knockout 还很陌生,我遇到了一个问题,我不知道如何解决。

我有一张信用卡额度表的视图。每行都有两个嵌套的下拉菜单,名为 Dimension1Key 和 Dimension2Key - 它们是通过 GetDimensionMatrix ajax 调用填充的。

creditlines foreach 填充在一个 for 循环中,其中两个下拉列表被定义为可观察的 - Dimension2 的数据被计算为 ko.compute。

表格和下拉列表最初使用选择的正确值正确填充 - 但嵌套无法正常工作。无论我更改了哪个 Dimension1 下拉菜单,self 的引用都指向表中的最后一行 - 因此使用最后一行的选定值中的值填充相应 Dimension1 的 Dimension2。 如果再次更改 Dimension1 值,则不会发生任何事情 - 对计算函数的引用被破坏。但是,如果我更改最后一行的 Dimension1 的值,则之前更改的行 Dimension2 的值会发生变化 - 就好像它的引用现在连接到最后一行一样。

我很确定问题是视图模型中循环中的 self - 以及它存在的上下文 - 但我无法理解解决方案。

有什么帮助吗? :-)

查看:

<section>
    <h2 data-bind="html:displayName"></h2>

    <table class="table">
        <tbody data-bind="foreach: creditCardLines">
            <tr>
                <td class="date" data-bind="text: Date"></td>
                <td class="date" data-bind="text: DocumentNo"></td>
                <td data-bind="text: Description"></td>
                <td><select data-bind="options: $parent.dimension1List, optionsText: 'DimensionValue', optionsValue: 'DimensionKey', value: Dimension1Key"></select></td>
                <td><select data-bind="options: dimension2List, optionsText: 'DimensionValue', optionsValue: 'DimensionKey', value: Dimension2Key"></select> </td>
                <td data-bind="text: Currency"></td>
                <td data-bind="text: CurrencyAmount"></td>
                <td data-bind="text: ExchangeRate"></td>
                <td data-bind="text: AmountLCY"></td>
                <td data-bind="text: Comment"></td>
                <td data-bind="text: ApprovedEmployee"></td>
                <td data-bind="text: Id"></td>
            </tr>
        </tbody>
    </table>
</section>

视图模型:

define(function (require) {

var submit = function () {
    this.displayName = 'Rejseafregning';

    this.creditCardLines = ko.observableArray();

    var me = this;

    this.activate = function () {
        return $.when(
                $.get('/submit/GetCreditCardLines'),
                $.get('/submit/GetDimensionMatrix')
                )
            .then(function (creditCardLines, dimension1List) {
                me.dimension1List = dimension1List[0].Data;

                for (var i = 0; i < creditCardLines[0].Data.length; i++) {
                    var self = creditCardLines[0].Data[i];

                    self.Dimension1Key = ko.observable(creditCardLines[0].Data[i].Dimension1Key);
                    self.Dimension2Key = ko.observable(creditCardLines[0].Data[i].Dimension2Key);


                    self.dimension2List = ko.computed(function () {
                        for (var j = 0; j < me.dimension1List.length; j++) {
                            if (me.dimension1List[j].DimensionKey === self.Dimension1Key()) {
                                return me.dimension1List[j].DimensionNext;
                            }
                        }
                    });

                    me.creditCardLines.push(self);
                }
            });
        };
    };
    return submit;
});

【问题讨论】:

    标签: drop-down-menu knockout.js nested durandal


    【解决方案1】:

    当您创建 ko.computed 时,您可以传入第二个参数,该参数在计算计算值时控制 this 的值。

    当您创建 dimension2List 计算值时,您可能希望将当前的 self 作为第二个参数传入,然后在如下方法中使用 this

                self.dimension2List = ko.computed(function () {
                    for (var j = 0; j < me.dimension1List.length; j++) {
                        if (me.dimension1List[j].DimensionKey === this.Dimension1Key()) {
                            return me.dimension1List[j].DimensionNext;
                        }
                    }
                }, self);
    

    否则,根据闭包在 JS 中的工作方式,重新计算计算结果时 self 的值最终会成为 self 设置的最后一个值(最后一行)。

    使用computed 的第二个参数确保该特定值将用作上下文。

    【讨论】:

    • 非常感谢 - 这是上下文 - 但不是我怀疑的 :-)
    猜你喜欢
    • 2012-02-14
    • 2015-12-20
    • 2018-08-30
    • 2017-12-26
    • 1970-01-01
    • 2012-08-23
    • 1970-01-01
    • 1970-01-01
    • 2017-03-30
    相关资源
    最近更新 更多