Jquery hide / show for knockout foreach loop

advertisements

inside foreach loop i have my content ...

                    <div foreach:"data">
             <input type="image" id="hideshow" src="/Images/aud_down-arrow.gif" />
           <div id="content">
         <textarea data-bind="text:valueoftext" rows='5' cols='60'></textarea>

        </div></div>
     jQuery(document).ready(function ()     {
    jQuery('#hideshow').live('click', function (event)     {
        jQuery('#content').toggle('show');
           });
});

Currently it creats the text boxes but only the first text box hide/show... Rest all textboxes in the loop dont work.

Any advice on how to make this work will be great.


OK, my best guess to fill in the blanks in your question is that you're generating that html in such a way that you've re-used the same id for every input and re-used the same id for every div. This results in invalid html because id must be unique on the page, and attempts to select elements by id JS/jQuery will only find the first.

What you need to do instead is give each input the same class attribute instead of id, and similar for the divs. It would make sense if each group of items was in its own <li> within a <ul>, or within its own <tr> within a <table>, so I suggest you do something like this:

<ul>
   <li>
       <input type="image" class="hideshow" src="/Images/aud_down-arrow.gif" />
       <div class="content">
          <textarea data-bind="text:valueoftext" rows='5' cols='60'></textarea>
       </div>
   </li>
   <li>
       <input type="image" class="hideshow" src="/Images/aud_down-arrow.gif" />
       <div class="content">
          <textarea data-bind="text:valueoftext" rows='5' cols='60'></textarea>
       </div>
   </li>
   <!-- etc. -->
</ul>

Then you can use jQuery's DOM navigation methods to find the div associated with each image:

jQuery(document).ready(function ()     {
    jQuery('.hideshow').live('click', function (event) {
        jQuery(this).closest("li").find("div.content").toggle('show');
    });
});

That is, when an image is clicked, navigate up the tree to the nearest containing <li> (or <tr> or whatever you are using) and then from there navigate back down within that container to the appropriate content.

Note that .live() is way out of date and should be replaced with .on() - give the containing element (the <ul> or <table> or whatever you're using) an id, say "mylist" and then do this:

jQuery('#mylist').on('click', '.hideshow', function() { ...

If for some reason you don't have each group of elements in a container and you really don't want to add containing elements, then you still need to change the ids to classes but can then do this:

    jQuery('.hideshow').live('click', function (event) {
        jQuery(this).next().toggle('show');
    });

I.e., select whichever element comes immediately after the clicked item and toggle it. The reason I recommend this only as a last resort is that it ties your JS closely to the structure of the html. Using the $(this).closest("someParentElement").find("associatedElement") type method is much more flexible and may not need to change if the html structure needs to change.