JQuery Tabs in C# MVC to stay on reload

Posted on

Problem

I am working on a C# MVC website. in which i am using tabs.I was trying to stay on the current tab when page refreshes.

I achieved this by following code:

$(document).ready(function () {
    if (window.location.href.indexOf("?") > -1) {
        var newURL = location.href;
        window.history.pushState('object', document.title, newURL);
    }
});
$(document).ready(function () {
    $('a[data-toggle="tab"]').on('show.bs.tab', function (e) {
        localStorage.setItem('activeTab', $(e.target).attr('href'));
    });
    var activeTab = localStorage.getItem('activeTab');
    if (activeTab) {
        $('#myTab a[href="' + activeTab + '"]').tab('show');
    }
});

This is working fine. But if the page is load by RedirectToAction from another page then it showing last opened tab, I needed to show the first tab.

So I added a hidden input field in the html.

<input type="hidden" value="@Model.IsRefresh" id="IsRefresh" />

On $(document).ready i change url as follows

$(document).ready(function () {
    if (window.location.href.indexOf("?") > -1) {
        var newURL = location.href.replace("?str=true", "");
        window.history.pushState('object', document.title, newURL);
    }
});

and in GET checks for this bool str and set IsRefresh as false

#region Check Is Page Refresh
if (str != null)
{
    if ((bool)str)
    {
        item.IsRefresh = false;
    }
    else
    {
        item.IsRefresh = true;
    }
}
else
{
    item.IsRefresh = true;
}
str = false;
#endregion

so if IsRefresh is false then it is page refresh and else it is RedirectToAction.

So i changed the code as:

$(document).ready(function () {
    $('a[data-toggle="tab"]').on('show.bs.tab', function (e) {
        localStorage.setItem('activeTab', $(e.target).attr('href'));
    });
    var activeTab = localStorage.getItem('activeTab');

    <!-- added these lines -->
    var refresgh = $("#IsRefresh").val();
    if (!refresgh) {
        activeTab = "";
    }

    if (activeTab) {
        $('#myTab a[href="' + activeTab + '"]').tab('show');
    }
});

Now its working fine, but sometimes i get the feeling that on page refresh different tab is showing. Is something wrong with my code?

Is there any better solution??

Solution

If browser compatibility matrix satisfies your requirements (see CanIUse) then there is a simpler way to check if page is reloaded, read window.performance.navigation.type value. For reload event value is TYPE_RELOAD then you may simply drop your hidden input and:

if (window.performance.navigation.type != 1) {
    activeTab = "";
}

See also W3C specs for further details.


If you’re not targeting IE you may want to use template literals instead of string concatenation, for example:

$(`#myTab a[href="${activeTab}"]`).tab('show');

Value you’re persisting in localStorage does not need to be retained across different sessions then you’d better use sessionStorage instead. It also has the advantage to be isolated by window (or tab).


You may want to use let and, where appropriate, const instead of var.


To put everything all together you may want to revert the condition you’re checking to simplify your code:

$(document).ready(function () {
    $('a[data-toggle="tab"]').on('show.bs.tab', function (e) {
        sessionStorage.setItem('activeTab', $(e.target).attr('href'));
    });

    if (window.performance.navigation.type === 1) {
        const activeTab = sessionStorage.getItem('activeTab');
        $(`#myTab a[href="${activeTab}"]`).tab('show');
    }
});

The recommended way to attach an handler to the ready event is:

$(function () {
    // ...
});

Absolutely nothing wrong with the verbose way (which BTW I find more clear).


I add this only because you may find it useful in future, to detect a page refresh may be done also server side, see asp.net mvc – Detecting page refresh.

Leave a Reply

Your email address will not be published. Required fields are marked *