Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get index of the clicked element in knockout

What is the best way to get index of clicked element of an unordered list?

Let me provide an example. Say I have the following HTML code:

<ul data-bind="foreach: listItems">
    <li data-bind="click: $parent.itemClicked">
         <p data-bind="text: title"></p>
    </li>
</ul>

Right now I have the following javascript code to get the index:

...

self.itemClicked = function(data, item) {
    var index = $(item.target).index();
}

...

But the problem is the if the target element is <p> for example, I get incorrect result. So how should I get the index of the clicked <li> element? Does knockout have some method for this or I should use jquery in some way?

like image 265
King Julien Avatar asked Nov 05 '12 17:11

King Julien


People also ask

How to bind click event in knockout?

The function you want to bind to the element's click event. You can reference any JavaScript function - it doesn't have to be a function on your view model. You can reference a function on any object by writing click: someObject. someFunction .

What is $data in knockout?

The $data variable is a built-in variable used to refer to the current object being bound. In the example this is the one of the elements in the viewModel.

What is $root in knockout?

$root. This is the main view model object in the root context, i.e., the topmost parent context. It's usually the object that was passed to ko. applyBindings . It is equivalent to $parents[$parents.

What is KnockoutJS used for?

KnockoutJS is basically a library written in JavaScript, based on MVVM pattern that helps developers build rich and responsive websites.


2 Answers

I recommend using Knockout's $index context property. See example below (JsFiddle):

HTML

<!DOCTYPE html>
<html>
<body>
<ul data-bind="foreach: listItems">
    <li data-bind="click: $parent.itemClicked.bind($data, $index())">
         <p data-bind="text: title"></p>
    </li>
</ul>
</body>
</html>
​

JavaScript

var vmodel = {
    listItems: ko.observableArray([
        {title: "Able"},
        {title: "Baker"},
        {title: "Charlie"}]),
    itemClicked: function(index) {
        alert(index);
    }
};
ko.applyBindings(vmodel);​
like image 53
Joseph Sturtevant Avatar answered Sep 29 '22 15:09

Joseph Sturtevant


Instead of messing up your binding, it's much prettier getting the index inside the event function. You can get the binding context from the event.target, using the ko.contextFor(element)

self.click = function (data, event) {
    var context = ko.contextFor(event.target);
    console.log(context.$index());
};
like image 37
Oleg Grishko Avatar answered Sep 29 '22 16:09

Oleg Grishko