Bootstrap Tabs in .NET with persist state after page refresh - c#

I am using native bootstrap tabs and trying to persist state of the current tab after the page refresh. Here is my form bootstrap 3 with Tabs:
<form runat="server" id="mainForm">
<div class="Tabs">
<ul class="nav nav-tabs">
<li runat="server" id="liSectionContractPayments" onclick="return makeActiveTab('sectionA');">
<a data-toggle="tab" href="#sectionA">
Heading 1
</li>
<li runat="server" id="liSectionTracking" onclick="return makeActiveTab('sectionB');">
<a data-toggle="tab" href="#sectionB">
Heading 2
</li>
<li runat="server" id="liSectionNotes>
<a data-toggle="tab" href="#sectionC" onclick="return makeActiveTab('sectionC');">
Heading 3</li>
</ul>
<div class="tab-content">
<div id="sectionContractPayments" class="tab-pane fade">
<h4>Heading 1</h4>
Content for heading 1
</div>
<div id="sectionTracking" class="tab-pane fade">
<h4>Heading 2</h4>
Content for heading 2
</div>
<div id="sectionNotes" class="tab-pane fade">
<h4>Heading 3</h4>
Content for heading 3
</div>
</div>
</div>
<%-- This is to keep the state of current tab. --%>
<asp:HiddenField ID="SetActiveNavTab" runat="server" />
</form>
I am using a hidden field SetActiveNavTab to persist state of the current tab, to do that I have the following script:
<script>
/* Not working ... */
function activaTab2(tab) {
$('.nav-tabs a[href="#' + tab + '"]').tab('show');
};
function makeActiveTab(activeTabName) {
$('#<%=SetActiveNavTab.ClientID%>').val(activeTabName);
activaTab2($('#<%=SetActiveNavTab.ClientID%>').val(activeTabName));
alert(activeTabName + "AND" + activaTab2($('#<%=SetActiveNavTab.ClientID%>').val()););
}
/* Not working ... */
$(document).ready(function() {
function activaTab(tab) {
$('.nav-tabs a[href="#' + tab + '"]').tab('show');
};
activaTab($('#<%=SetActiveNavTab.ClientID%>').val());
});
</script>
The part which is not working is marked with comments. I can't seems to save the clicked on tab to a SetActiveNavTab hidden field. Something wrong with the script?
Also not sure if there is a better way to do that?

You need to post the some part of page rather then full page post back. i-e AJAX
AJAX allows web pages to be updated asynchronously by exchanging small amounts of data with the server behind the scenes. This means that it is possible to update parts of a web page, without reloading the whole page.
HOW IT WORKS
Source
FOR AJAX IN ASP.NET WEB FORMS
In asp.net web forms you need to put update panel
Introduction to the UpdatePanel Control
Understanding ASP.NET AJAX UpdatePanel Triggers

Related

Rendering dinamically GenericHtmlControl/Literal merged with an Asp.net Control

My Environment is: ASP.NET 4.62 / C# / Boostrap 4 framework
My application renders bootstrap 4 menu from database query.
I've a div in aspx page
<div id="myNav" runat="server"></div>
and i add code behind as
myNav.InnerHtml = mystr.ToString()
Now i need to integrate in the menu a LoginView asp.net control.
Obviously if i add
<asp:LoginView id="LoginView1" runat="server" ViewStateMode="Disabled">
as string, the browser will receive a string a not renders a control ASP.NET.
I need to render something like this
....previous items menu
<asp:LoginView id="LoginView1" runat="server" ViewStateMode="Disabled">
<AnonymousTemplate>
<ul class='nav navbar-nav ml-auto'>
<li class='nav-item'>
<a class='nav-link' href='../../Account/Login.aspx'><span class='fas fa-user'>
</span>Login</a> </li>
<li class='nav-item'><a class='nav-link' href='~/Account/Login.aspx'>
<span class='fas fa-sign-in-alt'></span> Login</a> </li> </ul>
</AnonymousTemplate>
<LoggedInTemplate>
<ul class='nav navbar-nav ml-auto'>
<li class='nav-item'>
<a class='nav-link' href='~/Account/Login.aspx'><span class='fas fa-user'></span></a>
</li>
<li class='nav-item'>
<span class="myText">Hallo, </span><a runat="server" class="username"
href="~/Account/Manage.aspx" title="Profile">
<asp:LoginName runat="server" CssClass="username" />
</a>!
<asp:LoginStatus runat="server" LogoutAction="Redirect" LogoutText="Exit"
LogoutPageUrl="~/Logout.aspx" />
</li> </ul>
</LoggedInTemplate>
</asp:LoginView>
...closing boostrap menu tag
Which is best way to resolve this type of problem ?
I need to change approach ?
You are creating the HTML at the server side; that is a possibility, but as you see, it makes it hard to combine this with ASP.NET server controls.
It would be better to put the HTML on the .aspx-page. I understand that your database knows which menu-items should be visible. And that you want to add 1 additional item, where users can login.
You could use (for example) a GridView with one column.
<Columns>
<asp:TemplateField>
<ItemTemplate>
<div>Your HTML here </div>
<div><%# Item.SomeProperty %></div>
</ItemTemplate>
</asp:TemplateField>
</Columns>
Use the data from your database to render one 'row' per menuitem in the grid. You can customize the TemplateField so it contains the bootstrap-layout as you need it.
It might also be possible to keep your current approach. I think then you should at least not create your opening and closing bootstrap-menu tags in the code-behind. You should put those tags on the .aspx-page itself, the structure would then be:
<opening tag bootstrap menu>
<div id="myNav" runat="server"></div>
<asp:LoginView id="LoginView1" runat="server" ViewStateMode="Disabled"> ... </ ..>
<closing tag bootstrap menu>

Maintain Bootstrap tab on postback from gridview sorting event C#

I'm having a little trouble getting the Bootstrap tabs to persist during a postback which occurs when sorting gridviews.
I have tried the solutions listed in Remain bootstrap tab after postback c# and http://www.aspsnippets.com/Articles/Bootstrap-Tabs-Maintain-Selected-Active-Tab-on-PostBack-in-ASPNet.aspx to no avail.
My current code is:
<div role="tabpanel" id="Tabs">
<!-- Nav tabs -->
<ul class="nav nav-tabs" role="tablist" id="pageTabs">
<li role="presentation" class="active">Evidence Base</li>
<li role="presentation">Trials</li>
<li role="presentation">Resources</li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="EvidenceBase">
<div class="col-md-12">
<asp:GridView ID="EvidenceBaseGridView" runat="server" AllowPaging="true" AllowSorting="true" OnSorting="EvidenceBaseGridView_Sorting" OnPageIndexChanging="EvidenceBaseGridView_PageIndexChanging">
</asp:GridView>
</div>
</div>
<div role="tabpanel" class="tab-pane" id="Trials">
<div class="col-md-12">
<asp:GridView ID="TrialsGridView" runat="server" AllowPaging="true" AllowSorting="true" OnSorting="TrialsGridView_Sorting" OnPageIndexChanging="TrialsGridView_PageIndexChanging">
</asp:GridView>
</div>
</div>
<div role="tabpanel" class="tab-pane" id="Resources">
<div class="col-md-12">
<asp:GridView ID="ResourcesGridView" runat="server" AllowPaging="true" AllowSorting="true" OnSorting="ResourcesGridView_Sorting" OnPageIndexChanging="ResourcesGridView_PageIndexChanging">
</asp:GridView>
</div>
</div>
</div>
</div>
<asp:HiddenField ID="TabName" runat="server" ClientIDMode="Static" />
And the jQuery I have used to try to set the correct tab on postback is:
<script type="text/javascript">
$('#pageTabs').on('click', 'li a', function (e) {
var addressValue = $(this).attr('href').replace("#", "");
$('#TabName').val(addressValue);
});
$(document).ready(function () {
var tab = $('#TabName').val() != "" ? $('#TabName').val() : "EvidenceBase";
$('#pageTabs a[href="' + tab + '"]').tab('show');
});
</script>
I have inspected the value of the hidden field on postback and it seems to only set to the Trials tab and the page always defaults back to the Evidence Base tab. I have also tried removing the "active" class but that makes no difference other than not displaying a tab on initial page load.
Any help on this would be greatly appreciated as my jQuery knowledge is pretty limited.
Thanks.
Do not use UpdatePanels unless its absolutely necessary. You just have to set the value of asp:HiddenField at server-side, the maintain its state after postback. Setting it clientside wont work as it will be lost on postback.
You could set it on PageIndexChanging event itself like this.
protected void EvidenceBaseGridView_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
//page index changing logic here
TabName.Value = "EvidenceBaseGridView";
}
You can do the same for each GridView. Also, as you re-bind the GridView after firing each event, you could set the tab name after Databind.
ASP Answer
My immediate suggestion would be to use updatepanels.
<asp:ScriptManager runat="server></asp:ScriptManager>
<!-- Tab panes -->
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="EvidenceBase">
<asp:UpdatePanel runat="server">
<ContentTemplate>
<div class="col-md-12">
<asp:GridView ID="EvidenceBaseGridView" runat="server" AllowPaging="true" AllowSorting="true" OnSorting="EvidenceBaseGridView_Sorting" OnPageIndexChanging="EvidenceBaseGridView_PageIndexChanging">
</asp:GridView>
</div>
</ContentTemplate>
</asp:UpdatePanel>
</div>
...
This will allow the Gridviews to post back without refreshing the entire page. This means that the active class will not be re-set to the initial panel.
Note, any postbacks caused by a control outside of an UpdatePanel will refresh the entire page and thus re-set the active class on your panels.
Also note, don't forget to include your scriptmanager somewhere before your first UpdatePanel.
jQuery Answer
ASP.NET will have probably changed the ID of the hiddenfield to something like: ctl00_TabName., you may want to try $('[id*=TabName]') instead of $('#TabName') as your selector.
I find UpdatePanels useful for a backend system I've written, and use one for each bootstrap 3 tab and using the method I describe on the linked post below it works great for my website. Hopefully can help some other people too.
I have added my solution to the OP's question (not including my Updatepanels for simplicity) on the Remain bootstrap tab after postback c#
link above, which was after the OP said they tried the other answers in that post.

Dynamically hide JQuery UI Tabs

I have a .net c# webform using the JQueryUI tabs Example as per the code below:
<script type="text/javascript">
$(function () {
$("#tabs").tabs();
});
</script>
<div id="tabs">
<ul>
<li>Tab 1</li>
<li>Tab 2</li>
<li>Tab 3</li>
<li>Tab 4</li>
</ul>
<div id="divTab1">
Showing Tab 1
</div>
<div id="divTab2">
Showing Tab 2
</div>
<div id="divTab3">
Showing Tab 3
</div>
<div id="divTab4">
Showing Tab 4
</div>
</div>
What I would like to achieve, is based on a condition in my code behind, is to hide specific tabs.
How would I go about doing this?
You can call the JQuery hide() method:
http://api.jquery.com/hide/
In code-behind, evaluate your conditions and register the hide() method invocation with ClientScriptManager.RegisterStartupScript method:
http://msdn.microsoft.com/en-us/library/system.web.ui.clientscriptmanager.registerstartupscript.aspx

Posting data in Tab based page by partialview

I have 3 tabs in my Page and I used JQuery UI for tabs.
<div id="tabs" style="text-align:right;">
<ul>
<li class="myTab">
Main Information</li>
<li class="myTab"><a href=<%= Url.Action("GetPartialView","Contractors") %> >Contractors</a></li>
<li class="myTab"> Consultants </li>
</ul>
<div id="tabs-1">
</div>
<div id="tabs-2">
</div>
<div id="tabs-3">
</div>
There is a "Save" button in each tab.The problem is that when for example button "Save" of contractors tab was clicked the page redirect to http://localhost:1347/xxxxx/GetPartialView and didn't fire any method.I want to save data and show user a message that shows data was saved completely.How can I do it?
Do you have the [HttpPost] attribute on top of whatever action is being called to load that page?

Drag-and-drop accordion panels? (ASP.Net)

I have a set of accordion panes(dynamically created) contained in an Accordion control. Basically, what I am wanting is for the user to be capable of dragging these accordion panels so that instead of
A pane
B pane
C pane
They can drag and drop it to be something like
B pane
A pane
C pane
Or whatever. Also, more importantly, I would need to be able to detect that they have changed the order. Would there be a way to have it when they "drop" the pane that it can update a hidden field or something? I don't need a postback on every single drag and drop, but rather I want for when they hit a save button for the server application to detect the order in which the panes are so that it can save this order.
I would prefer to stay away from javascript libraries, but if it would be the easiest way, then I'll consider it.
Based on petersendidit's answer but without "disappearing accordion" bug...
<div id="accordion">
<div id="section_1">
<h3>Section 1</h3>
<p>
Body 1
</p>
</div>
<div id="section_2">
<h3>Section 2</h3>
<p>
Body 2
</p>
</div>
<div id="section_3">
<h3>Section 3</h3>
<p>
Body 3
</p>
</div>
<div id="section_4">
<h3>Section 4</h3>
<p>
Body 4
</p>
</div>
</div>
and
$("#accordion").accordion({
header:'h3'
}).sortable({
items:'>div'
});
Demo at: https://jsbin.com/bitiyucasa
You can do something like this with jQuery UI:
$("#accordion").accordion()
.sortable({
items:'>.ui-accordion-header',
change: function(event, ui) {
$content = ui.item.next();
},
stop: function(event, ui) {
ui.item.after($content);
}
});
This sets $content to the content div for that header on change. And then on stop moves that content to be after the new position of the header.
HTML would be something like:
<div id="accordion">
<h3 id="section_1">Section 1</h3>
<div>
<p>
Body 1
</p>
</div>
<h3 id="section_2">Section 2</h3>
<div>
<p>
Body 2
</p>
</div>
<h3 id="section_3">Section 3</h3>
<div>
<p>
Body 3
</p>
</div>
<h3 id="section_4">Section 4</h3>
<div>
<p>
Body 4
</p>
</div>
</div>
When your user hits the "save" button you can just call:
$('#accordion').sortable( 'serialize');
Which will give you something like:
section[]=2&section[]=1&section[]=3&section[]=4
This widget is probably the sort of thing you are after.
You can add links to the javascript in the head
<link rel="stylesheet" type="text/css" href="accordion.css">
<script type="text/javascript" src="Ext.ux.InfoPanel.js"></script>
<script type="text/javascript" src="Ext.ux.Accordion.js"></script>
The markup is then just a series of divs. With a little bit of effort you should be able to tie this into the accordion control or create a user control to do your bidding
<div id="acc-ct" style="width:200px;height:300px">
<div id="panel-1">
<div>My first panel</div>
<div>
<div class="text-content">My first panel content</div>
</div>
</div>
<div id="panel-2">
<div>My second panel</div>
<div>
<div class="text-content">My second panel content</div>
</div>
</div>
</div>
A preview of it is available here
Hope this helps
You could use predefined dojo control (open source javascript framework)(link text) and use this control from here (link text) .You can also integrate dojo with asp.net like on my blog (link text).
Waiting for response of your success

Categories