Show Hide table tr on click of parent tr

I am trying to hide and show a tr row which sits beneath its parent tr, I can get the console.log to display the message on click but the hidden tr want toggle open.

.hiddenTR {
    display: none;
}
.ShowHide {
    cursor: pointer;
}

$(function () {

    $(document).on('click', "#tblActionsByAudit", function (event) {
        console.log("hello");
        // find where the click originated from
        var trigger = event.target;

        // if it has a class of "ShowHide"
        // THEN toggle the next row
        if (trigger.className === 'ShowHide') {
            // toggle away
            $(trigger).closest('tr').next('.hiddenTR').toggle();
        }
    });

});

<tbody>
        @foreach (var record in Model.ActionsByAudit)
        {
                <tr class="alignCenter ShowHide">
                <td>
                    @record.Property
                </td>
                <td data-datatype="date">
                    @record.AuditDate.ToString("yyyy-MM-dd")
                </td>
                <td>
                    @record.Module
                </td>
                <td>
                    @if (record.ActionsCompleted == record.ActionsGenerated)
                    {
                        <span>@record.ActionsCompleted / @record.ActionsGenerated</span>
                    }
                    else
                    {
                        <span style="color:red">@record.ActionsCompleted / @record.ActionsGenerated</span>
                    }
                </td>
                <td>
                    @record.ActionsCompletedPercentage
                </td>
            </tr>
            <tr class="alignCenter hiddenTR">
                <td colspan="5">Hidden</td>
            </tr>
        }
    </tbody>

Its definitly a jquery issue, but cant work it out

Well, let’s start with an somewhat unrelated, but notable point:

if you’re putting this event on the TABLE…

if (trigger.className === 'ShowHide') {
Will never be true. trigger points to the table.

And even if you’ve classed the table as ‘ShowHide’,

$(trigger).closest('tr').next('.hiddenTR').toggle();

closest only spirals UP the DOM, not DOWN. It will never find the TR you’re hunting for.

It’s impossible to bind an event to a table that can identify what row has been clicked on; you should be binding your event to the rows instead.

(As an aside, if you do bind the event to the row, .closest('tr') is redundant, because trigger is already the row.)

Right ok, Umm but I cant use an id on the tr as the id will duplicate and then I will have multiple the same id’s.

And yes I see with the closest issue, would you be able to help me with this m_hutley

So I slightly changed it to this below, and to test put the id event on the tr

    $(document).on('click', "#tableRowShowHide", function (event) {
        console.log("funny");
        // find where the click originated from
        var trigger = event.target;

        // toggle the next showhide row
        if (trigger.className === 'ShowHide') {
            // toggle
            $(trigger).next('.hiddenTR').toggle();
        }
    });

<tr class="alignCenter ShowHide" id="tableRowShowHide">
                <td>
                    @record.Property
                </td>
                <td data-datatype="date">
                    @record.AuditDate.ToString("yyyy-MM-dd")
                </td>
                <td>
                    @record.Module
                </td>
                <td>
                    @if (record.ActionsCompleted == record.ActionsGenerated)
                    {
                        <span>@record.ActionsCompleted / @record.ActionsGenerated</span>
                    }
                    else
                    {
                        <span style="color:red">@record.ActionsCompleted / @record.ActionsGenerated</span>
                    }
                </td>
                <td>
                    @record.ActionsCompletedPercentage
                </td>
            </tr>
            <tr class="alignCenter hiddenTR">
                <td colspan="5">Hidden</td>
            </tr>

Correct, you cant use an ID on the row. But you can use a class selector for your bind instead of an ID.

In fact, when you do use it, you will eliminate the need for the if check entirely.

$(document).on("click",".ShowHide", function....

Sorry but I don’t think so.

The target property can be the element that registered for the event or a descendant of it.
source: https://api.jquery.com/event.target/

It also works in my testing without jQuery either.

@Paul_Wilkins: Fair, but wouldnt you think the extremely higher chance is that the event.target in that case would be a td? or something inside the td?

Much better to target correctly and use the correct verbage ($(this)) .

Yes, the event target is highly likely to be that, which is why he attempts to get from there to the nearest tr element.
$(trigger).closest('tr').next('.hiddenTR').toggle();

I suppose. It’s still sloppy, and the reason that $(this) exists.

I find that the this keyword ends up becoming confusing, resulting in too much tracing of the code to figure out in just which context the this keyword is being used.

But I digress - sorry to have disturbed. I return you back to what was being done before.

Though Paul’s point brings up probably why the code is failing - event.trigger diving so deep that the if statement never returns true, because you’ve actually clicked on a td or span that doesnt have the ShowHide class.

Thanks for helping guys, I have put it back to using the table id, and then returning the jquery as was, just not sure what to use now. Its currently like this:

    $(document).on('click', "#tblActionsByAudit", function (event) {
        console.log("funny");
        // find where the click originated from
        var trigger = event.target;

        // toggle the next showhide row
        if (trigger.className === 'ShowHide') {
            // toggle
            $(trigger).closest('tr').next('.hiddenTR').toggle();
        }
    });

<tr class="alignCenter ShowHide">
                <td>
                    @record.Property
                </td>
                <td data-datatype="date">
                    @record.AuditDate.ToString("yyyy-MM-dd")
                </td>
                <td>
                    @record.Module
                </td>
                <td>
                    @if (record.ActionsCompleted == record.ActionsGenerated)
                    {
                        <span>@record.ActionsCompleted / @record.ActionsGenerated</span>
                    }
                    else
                    {
                        <span style="color:red">@record.ActionsCompleted / @record.ActionsGenerated</span>
                    }
                </td>
                <td>
                    @record.ActionsCompletedPercentage
                </td>
            </tr>
            <tr class="alignCenter hiddenTR">
                <td colspan="5">Hidden</td>
            </tr>

Im stuck lol

Try this:
var trigger = event.target;
=>
var trigger = $(event.target).closest('tr');

Cheers m_hutley, still not opening up the hidden tr, am ok to use the table id too as the click function id as below

    $(document).on('click', "#tblActionsByAudit", function (event) {
        console.log("funny");

        var trigger = $(event.target).closest('tr');

        if (trigger.className === 'ShowHide') {

            $(trigger).closest('tr').next('.hiddenTR').toggle();

        }
    });

k… next step in sorting out this insistence is probably the classname check…

if (trigger.className === 'ShowHide') {
=>
if (trigger.hasClass('ShowHide')) {

1 Like

BOOM!

Thank you :slight_smile:

for the record, the properly scoped version of this code is boiling the entire block down to:
$(".ShowHide").click(function() { $(this).next(".hiddenTR").toggle(); });

Be careful with that though, because it fails to work with other DOM elements that are added to the page.

#1: He doesnt indicate he’s dynamically creating elements.
#2: He’s already got the block wrapped in a onload
#3 it’s still the correct code.

Jeezus Paul, I do something to you today?

Thanks guys,

I am following the discussion, and very happy it works.

Might be pushing it but is it possible to slide the hidden tr instead of show, if not no worries, very happy, thank you both