knockoutjs click binding not working in nested foreach

Kimpo picture Kimpo · May 15, 2012 · Viewed 9.3k times · Source

So i have a really weird problem with a knockoutjs click binding not getting attached to anchor tags. Other data-bind="" works but not the click binding.

Below you can see the HTML and part of the viewmodel js file

var tag = function (data) {
    this.count = data.Count;
    this.id = data.Id;
    this.title = data.Title;
    this.tagGroup = data.TagGroup;
};
 var tagContainer = function (data) {
    this.tagList = $.map(data.Tags, function (item) { return new tag(item); }); 
    this.letter = ko.observable(data.Letter);
};

var searchViewModel = function(){
   var self = this;

   self.tagContainerList = ko.observableArray([]); 

   self.addFilter = function (tag) { 
    //move tag to active filters and do some more cool stuff here 
    };


};

<div id="modal-all-tags" data-bind="with:searchViewModel">
    <ul data-bind="foreach:tagContainerList">
        <li>
            <span data-bind="text:$data.letter()"></span>
            <ul data-bind="foreach:tagList">
                <li><a href="#" data-bind="click:$root.addFilter"><span data-bind="text:title"></span></a></li>

            </ul>
        </li>
    </ul>

      <a class="close-reveal-modal">&#215;</a>
</div>

Basically it is a modal popup and its loaded when user clicks a link on the page. I send a request to server and it returns me a list of Tag Containers each have the starting Letter and a list of tags to be rendered below the letter like this: A a word 1 a word 2 B b word 1 b word 2 C c word 1 c word 2

and so on...

The letters are rendered correctly A,B,C and each gets the correct tag list rendered below them with text:title displaying correctly.

Everything works except the addFilter(); function that i want to bind to each link in the taglist. The browser just jumps up and adds a hash character to the url. Firebug is not showing any errors on bindings either.

The reason the div container has a with:searchViewModel is because there is a master viewmodel for the whole page. But this should not matter since it is working on every other page of the project.

The only thing i can think of is that the click binding $root.addFilter is wrong but i tried just addFilter where firebug gives the error "addFilter is not defined;"

And i tried both $parent and $root.

Does anyone have any suggestions?

Answer

Mark Robinson picture Mark Robinson · May 15, 2012

One thought I've had. Your addFilter function expects a parameter (tag) but you are not passing it anything in the binding:

<a href="#" data-bind="click:$root.addFilter">

Could this be the problem?

Maybe something along the lines of:

<a href="#" data-bind="click:function() { $root.addFilter($data) }">

would help?