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.