Knockout.JS:如何在自定义绑定中使用事件

时间:2015-07-22 21:42:17

标签: knockout.js

以下代码适用于早期版本的KO(2.x),但在新版本(3.x)中失败。单击超链接应在视图模型中调用函数showSectionName。我得到的错误是:

Uncaught TypeError: Cannot read property '$data' of undefined

检查我的小提琴here

检查与KO 2.x here

一起使用的非常相似的版本

我的HTML:

    <div style="width:200px">
    <ul class="nav nav-pills nav-stacked" data-bind=" template: { name: 'itemTmpl', foreach: sections, templateOptions : { select: showSectionName }}"></ul>

    <script id="itemTmpl" type="text/html">
        <li role="presentation" data-bind="bootstrapHyperlink: { action: $data.select, params: [ $data ] }">
        </li>
    </script>

</div>

我的剧本:

        $(function () {

        ko.bindingHandlers.bootstrapHyperlink = {
            init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
                var elt = "<a href='#'>" + viewModel.name + "</a>";
                $(element).append(elt);

                var options = valueAccessor();
                var newValueAccessor = function () {
                    return function () {
                        options.actions.apply(context, options.params);
                    };
                };
                ko.bindingHandlers.click.init(element, newValueAccessor, allBindings, bindingContext);
            },

        }

        Section = function (id, name) {

            var self = this;

            self.id = id,
            self.name = name
        };


        function viewModel() {
            var self = this;
            self.sections = ko.observableArray(
            [
            new Section(10, "Section 1"),
            new Section(20, "Section 2"),
            new Section(30, "Section 3")
            ])

            self.showSectionName = function (item) {
                alert("You clicked the section " + item.name);
            }

        }
        ko.applyBindings(new viewModel());
    });

2 个答案:

答案 0 :(得分:2)

基本上我认为您遇到的问题是templateOptions在模板绑定文档中没有提及它,这个问题看起来有点https://github.com/knockout/knockout/issues/365

我更新了小提琴https://jsfiddle.net/c2fe9bs8/4/

要避免使用templateOptions,您可以使用$parent特殊属性来访问您的viewModel,如下所示:

<li role="presentation" data-bind="
    bootstrapHyperlink: { action: $parent.showSectionName, params: [ $data ] }
"></li>

这是一个意见问题,但是由于您已经在使用jQuery并且如果删除了节点,则删除事件处理程序也可能更容易绑定到click事件:

ko.bindingHandlers.bootstrapHyperlink = {
    init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
        var options = valueAccessor();

        var link = $('<a href="#">' + viewModel.name + '</a>');

        $(element).append(link);
        link.on('click', function () {
            options.action.apply(bindingContext, options.params);
        });
        ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
            link.off('click');
        });
    }

}

答案 1 :(得分:0)

脚本:

<script type="text/javascript">
    $(function () {

        ko.bindingHandlers.bootstrapHyperlink = {
            init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
                var elt = "<a href='#'>" + viewModel.name + "<span class='badge'>" + viewModel.id + "</span></a>";
                $(element).append(elt);

            },

        }

        Section = function (id, name) {

            var self = this;

            self.id = id,
            self.name = name
        };


        function viewModel() {
            var self = this;
            self.sections = ko.observableArray(
            [
            new Section(10, "Section 1"),
            new Section(20, "Section 2"),
            new Section(30, "Section 3")
            ])

            self.showSectionName = function (item) {
                alert("You clicked the section " + item.name);
            }

        }
        ko.applyBindings(new viewModel());
    });
</script>

HTML:                  

        <li role="presentation" data-bind="bootstrapHyperlink: { action: $index.select, params: [ $index ] }, click:$root.showSectionName">
        </li>
    </ul>

</div>