knockoutjs click binding not working in nested foreach
Asked Answered
F

3

9

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?

Furrier answered 15/5, 2012 at 11:10 Comment(1)
Would you explain how you solved it, I would highly appreciate it.Lauro
A
15

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?

Although answered 15/5, 2012 at 11:29 Comment(9)
It does unfortunately not work getting $parent.addFilter is not a function tried with $root aswell. But it did give me an idea, i will try some things with that approach.Furrier
Still no luck, i am using the click:addFilter in other parts of the page where you can add search filters and the $data is usually not required if you are for example calling a function when iterating through an observable arrayFurrier
Sorry to hear that. You say that "Firebug is not showing any errors on bindings either." This would imply your addFilter function is getting called otherwise an error would be raised. Have you tried putting a breakpoint on the addFilter function (I find Chrome very good for debugging knockout) and see if there problem lies inside the function? I suggest you inspect what is being passed in the tag parameter and see if that is the problem.Although
No binding errors in firebug, thats what usually helps me find the errors but this time its just quiet :( The click binding is never attached to the anchor tag since not even the preventDefault behaviour is run, meaning the browser tries to navigate to #Furrier
I'm stuck then, Kimpo. Either time to add a jsFiddle to your question or maybe another SO user will step up. Sorry!Although
Thanks for the tip, i will try to reproduce it in jsfiddleFurrier
ok, got it working now. it was actually the outer viewmodel messing up things. so i could not refer to the child viewmodel from the nested foreach.... ehhh .ye that made sense :) well it is working anywaysFurrier
i will still give you credit Mark even though it wasnt direct answer. The discussion got my brain working again which led me to find the problem :D cheers!Furrier
That's very kind, Kimpo. Thanks. And more importantly, glad you got it working.Although
L
4

I ran into something similar and at first I ran data-bind="click:function() { console.log($parents) }". Note that its $parents not $parent. I looked to find the context, and the one I needed looked something like data-bind="click:$parents[1].onCardClick"

Lomasi answered 1/10, 2014 at 15:9 Comment(2)
Xerri offered a very viable solution, I was stuck in exactly the same situation and it solved my problem. only change i made was to put parentheses data-bind="click:$parents[1].onCardClick() and it worked as charm.Cacoepy
This was my issue also, a click binding inside a nested foreach loop wouldn't work with $parent.onCardClick and also wouldn't work with $root.onCardClick (it said root undefined). This is a great solution.Shudder
A
1

I found in ko context and try to use sample like below. $parentContext.$parent.onButtonClick

Abc answered 26/1, 2021 at 6:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.