Typescript KnockoutJS点击绑定错误

时间:2015-02-23 17:24:39

标签: knockout.js typescript

一起开始使用Typescript和KnockoutJS,我已经找到了一个我无法推理的错误。 HTML如下所示:

<div class="panel panel-body">
    <div class="list-group" data-bind="foreach: Items()">
        <a href="#" class="list-group-item"
           data-bind="text:Name, click: $parent.SetCurrent">
        </a>
    </div>
</div>

打字稿如下:

/// <reference path="knockout.d.ts"/>
/// <reference path="jquery.d.ts" />

module ViewModels {
    export class ItemViewModel {
        public Name: KnockoutObservable<string>;

        constructor(name: string) {
            this.Name = ko.observable(name);
        }//constructor
    }

    export class MainViewModel {
        public SelectedItem: KnockoutObservable<ItemViewModel>;
        public Items: KnockoutComputed<Array<ItemViewModel>>;

        constructor() {
            this.SelectedItem = ko.observable<ItemViewModel>();
            this.Items = ko.computed({
                owner: this,
                read: () => {
                    return this.get_items();
                }
            });
        }

        //TODO: replace this with knockout.mapping plugin transforms
        private convert_from_model(items_model) {
            var arr = new Array<ItemViewModel>();
            var owner = this;
            items_model.forEach(function (item) {
                var d = new ItemViewModel(item.name);
                arr.push(d);
            });
            return arr;
        }

        private get_items(): Array<ItemViewModel> {
            var items = [{ "name": "AAAA" }, { "name": "BBBB" }, { "name": "CCCC" }, { "name": "DDDD" }];

            var items_c = this.convert_from_model(items);
            return items_c;
        }

        public SetCurrent(item: ItemViewModel) {
            this.SelectedItem(item);
        }
    }
}

window.onload = () => {
    ko.applyBindings(new ViewModels.MainViewModel());
};

问题是在点击事件上设置当前项目。

public SetCurrent(item: ItemViewModel) {
    this.SelectedItem(item);
}

点击事件正确调用 SetCurrent ,但&#39; this&#39;是 ItemViewModel 类型,而不是 MainViewModel 。我错过了一些明显的东西吗?

这里有一个VS2013 solution,可以解决所有问题。

由于

3 个答案:

答案 0 :(得分:6)

click: $parent.SetCurrent

Knockout始终调用事件处理程序,并将this设置为当前视图模型。此特定绑定意味着(向Knockout)&#34;使用当前视图模型调用$parent.SetCurrent this&#34;。

最简单的解决方法是使用箭头功能始终拥有正确的this

    // Change the definition of SetCurrent like so:
    public SetCurrent = (item: ItemViewModel) => {
        this.SelectedItem(item);
    }

答案 1 :(得分:3)

原来这是一个常见的绑定错误。 解决方案是强制绑定

<a href="#" class="list-group-item"
           data-bind="text:Name, click: $parent.SetCurrent.bind($parent)">
</a>

答案 2 :(得分:1)

您需要在SetCurrent的闭包中捕获this或将$parent.SetCurrent绑定到$parent。对于前者,Typescript提供了一种使用lambdas执行此操作的好方法,但请注意,将不再在MainViewModel的原型上定义SetCurrent:

SetCurrent = (item: ItemViewModel) => {
    this.SelectedItem(item);
}

对于后者,将点击绑定更改为$parent.SetCurrent.bind($parent)