【问题标题】:In Knockout, how can I delay databinding until an array is populated?在 Knockout 中,如何延迟数据绑定直到填充数组?
【发布时间】:2014-01-10 04:40:40
【问题描述】:

我已经多次遇到这种模式,但还没有找到一种优雅的方式来处理它。我正在尝试设置具有只读和编辑模式的页面。

这里是html:

<div>
    <span data-bind="text: EventType, if: !EditMode()"></span>
    <select data-bind="options: $root.EventTypes, optionsValue: 'Id', 
        optionsText: 'Name', value: EventType, if: EditMode()"></select>
</div>
<div>
    <a href="#" data-bind="click: edit">Edit</a>
</div>

还有 javascript:

function viewModel(eventJSON) {
    var self = this;

    self.EventType = ko.observable(eventJSON.EventType);
    self.EventTypes = ko.observableArray([]);

    self.edit = function() {
        $.getJSON("url...", function(eventTypesJSON) {
            self.EventTypes(eventTypesJSON);
        }
    }
}

我遇到了数据绑定的计时问题。当调用 applyBindings 时,span 会被正确填充。但是,当我进入编辑模式时,下拉列表未设置为所选值,并且 EventType 设置为未定义。

这是我认为正在发生的事情:

  1. 用户单击“编辑”按钮并进行 ajax 调用以检索 事件类型。
  2. 选择是数据绑定的。由于 EventTypes 数组为空,因此 EventType 设置为 null。
  3. ajax 调用完成,EventTypes 被填充。
  4. 由于 EventType 先前设置为 null,因此选择了下拉列表中的第一项。 (例如,原来的 EvenType 值丢失了。)

我希望它做什么:

  1. 用户单击“编辑”按钮并进行 ajax 调用以检索 事件类型。
  2. ajax 调用完成并填充 EventTypes 数组。
  3. 选择是数据绑定的,并且选择了列表中的正确项目。

【问题讨论】:

  • 为什么不用最初选择的事件类型(即 self.EventTypes = ko.observableArray([eventJSON.EventType]);)简单地初始化 EventTypes 数组?
  • 我做了一些测试,它应该可以工作 - 添加了一个答案。

标签: knockout.js


【解决方案1】:

我相信我今天遇到了同样的问题并找到了解决方案:

  • SELECT 从可观察数组中获取选项的值和文本。
  • 可观察数组的数据在视图模型的其余部分被填充后加载。
  • 数组的选定值来自视图模型的另一个字段。

我能够通过将所选值传递给从 Web 服务调用加载数组的函数来使其工作。调用完成后,我将值分配回最初用作选定值的可观察对象。这样做会强制该字段的订阅者重新绑定,以便现在正确填充的 SELECT 更改所选值。

我知道这对你来说已经晚了,可能不完全是你的情况,但听起来很相似,可能对其他人有帮助。

【讨论】:

    【解决方案2】:

    不要将 EventTypes 数组设置为空,而是使用最初选择的事件类型引导它,这样在选择时它不会清除 EventType 值启用。一旦 ajax 从调用返回,内容无论如何都会被覆盖。即:

    self.EventTypes = ko.observableArray([eventJSON.EventType]);
    

    或者,如果由于某种原因您无法预先初始化数组,并且由于初始事件仍在 ajax 回调的范围内,只需在加载数组后重置 EventType

    $.getJSON("url...", function(eventTypesJSON) {
       self.EventTypes(eventTypesJSON);
       self.EventType(eventJson.EventType);
    }
    

    在后者中,请注意不要将初始视图模型参数与ajax回调中的名称使用相同的名称,否则后者将覆盖第一个。

    【讨论】:

    • 我的示例没有显示它,但 EventTypes 实际上是对象而不是字符串,因此我无法使用 eventJSON.EventType 初始化数组。
    • 我明白了,我没有注意到“optionsValue”和“optionsText”绑定 - 无论如何我认为 KO 只关心它需要在绑定中使用的属性,所以假设初始 eventJSON .EventType 值等于 eventTypesJSON 中返回对象的 id 属性(这是 KO 可以识别新数组中对应于先前选择的项的唯一方法),您仍然可以使用“虚拟”对象预加载数组:self.EventTypes = ko.observableArray([{Id: eventJSON.EventType, Name: 'some fake name'}]);
    • 感谢您对此进行调查。我们从来没有让它工作。目前,我们只是预加载所有查找表,以便保证数据可用。
    猜你喜欢
    • 1970-01-01
    • 2013-10-20
    • 1970-01-01
    • 2014-05-24
    • 1970-01-01
    • 2011-09-23
    • 1970-01-01
    • 2011-08-03
    • 2016-01-18
    相关资源
    最近更新 更多