淘汰数据绑定

时间:2016-08-24 10:22:15

标签: knockout.js typescript

我有一个基于递归结构的淘汰视图模型(用typescript编写)。简化版如下:

class ReportGroupViewModel {
    constructor(name?: string, subGroups?: ReportGroupViewModel[]) {
        this.name = ko.observable(name || '');
        this.subGroups = <KnockoutObservableArray<ReportGroupViewModel>>(ko.observableArray(subGroups || []));
    }

    name: KnockoutObservable<string>;
    subGroups: KnockoutObservableArray<ReportGroupViewModel>;

    addSubGroup(): void {
        this.subGroups.push(new ReportGroupViewModel());
    }

    deleteSubGroup(subGroup: ReportGroupViewModel): void {
        console.log(this.name());
        this.subGroups.remove(subGroup);
    }
}

在我看来,我使用递归模板列出组。

<ul data-bind="template: { name: 'subGroupTemplate', foreach: subGroups }"></ul>

简化模板如下:

<script id="subGroupTemplate" type="text/html">

    <span class="item-actions pull-right">
        <span data-bind="click: addSubGroup">Add Sub Group</span>
        <span data-bind="click: $parent.deleteSubGroup">Delete Sub Group</span>
    </span>

    <li>
        <input type="text" data-bind="textInput: name" placeholder="Name"/>
    </li>

    <ul data-bind="template: {name: 'subGroupTemplate', foreach: subGroups }"></ul>

</script>

我遇到的问题是删除绑定不会在父对象上触发,而是在子对象上触发(即它就像绑定是data-bind="click: deleteSubGroup"一样,没有$parent.)从登录到JS控制台的名称中可以看到。我在https://jsfiddle.net/po173qqh/3/

创建了一个jsfiddle

我做错了什么导致在层次结构的错误级别调用deleteSubGroup方法?

2 个答案:

答案 0 :(得分:1)

输入$parent.deleteSubGroup即可参考$parent中的方法。尽管如此,仍然使用$data作为this来调用该方法。您必须告诉必须通过绑定将$parent用作this

<span data-bind="click: $parent.deleteSubGroup.bind($parent, $data)">Delete Sub Group</span>

或者,您可以使用var self = this模式并在方法中使用self,但我不确定它在Typescript中是如何工作的......

修改:这可能是小提琴打字稿转换,但我必须移除{}内的applyBindings来修复它:https://jsfiddle.net/qf66w75p/

编辑2:正如Tsvetomir Nikolov在评论中建议的那样,您还可以使用箭头函数将函数显式绑定到父上下文。绝对是最干净的选择。谢谢,Tsvetomir! https://jsfiddle.net/y9ax95fy/

答案 1 :(得分:0)

如果使用Knockout Punches,则由“Wrapped event callbacks”预处理器自动修复,然后您可以使用现有的绑定和视图模型。解释:

  

将模型中的函数绑定到事件时,很容易简单地为绑定提供函数引用,例如click: $parent.removePlace。但是,当以这种方式绑定时,对$parent的引用将丢失;将使用默认removePlace值(当前模型对象)调用this方法。