user1309226
user1309226

Reputation: 759

With Knockout.JS how to attach an event handler using custom binding handler

My binding handler adds a hyperlink to a list item tag. I would like to know how to attach click event to the hyperlink through the binding handler. The click event should call a function within the view model.

You can see code in this jsfiddle.

So my question is: How to attach an event handler to call showSectionName from the view model? Maybe using something like ko.bindingHandlers.click(...)?

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

    var Section = function (id, name) {
        var self = this;

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

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

    function viewModel() {
        var self = this;
        self.Sections = ko.observableArray([
            new Section(1, "Section 1"),
            new Section(2, "Section 2"),
            new Section(3, "Section 3")
        ])
    }
    ko.applyBindings(new viewModel());
});
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<div style="width:200px">
    <ul class="nav nav-pills nav-stacked" data-bind="foreach:Sections">
        <li role="presentation" data-bind="bootstrapHyperlink: {click: showSectionName($data)}">
        </li>
    </ul>
</div>

Upvotes: 1

Views: 707

Answers (3)

shammelburg
shammelburg

Reputation: 7308

You can try this,

I hope this is more like what you were after: JSFiddle

<div style="width:200px">
    <ul class="nav nav-pills nav-stacked" data-bind="foreach:Sections">
        <li role="presentation" data-bind="bootstrapHyperlink: name"></li>
    </ul>
</div>

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

            $(element).on('click', function () {
                alert($(this).text());
            });
        }
    }

    Section = function (id, name) {

        var self = this;

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

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

        self.showSectionName = function (data) {
            alert("You clicked the section " + data.name);
        }
    }
    var vm = new viewModel();
    ko.applyBindings(vm);
});

Upvotes: 1

Tomalak
Tomalak

Reputation: 338208

There is no need for advanced techniques like custom binding handlers for your problem.

You ought not to build HTML with jQuery when you use knockout. Knockout builds all your HTML for you. Consider this simple example:

function Section(id, name) {
    this.id = id;
    this.name = name;
}
Section.prototype.showSectionName = function () {
    alert("You clicked '" + this.name + "'");
}

function ViewModel() {
    var self = this;
    self.sections = ko.observableArray([
        new Section(1, "Section 1"),
        new Section(2, "Section 2"),
        new Section(3, "Section 3")
    ]);
}

$(function () {
    ko.applyBindings(new ViewModel());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div style="width:200px">
    <ul class="nav nav-pills nav-stacked" data-bind="foreach: sections">
        <li role="presentation">
            <a href="#" data-bind="text: name, click: showSectionName"></a>
        </li>
    </ul>
</div>

Note that using the prototype only works for regular functions, not for knockout's computed values.

Upvotes: 2

Roy J
Roy J

Reputation: 43881

See here for ko.utils.registerEventHandler

But it also looks like this might be a good use for ko.components.

Upvotes: 1

Related Questions