ASP.NET LinkButton not firing inside of Bootstrap Tabs - asp.net

Using Bootstrap's Tabs, ASP.NET LinkButtons are not firing events while inside of the tab-content div.
HTML
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active" runat="server" id="liQuestions" href="#questions" role="tab" data-toggle="tab">
<asp:Button runat="server" ID="btnQuestions" />
</li>
<li role="presentation" class="active" runat="server" id="liComments" href="#comments" role="tab" data-toggle="tab">
<asp:Button runat="server" ID="btnComments" />
</li>
<li role="presentation" class="active" runat="server" id="liAttachments" href="#attachments" role="tab" data-toggle="tab">
<asp:Button runat="server" ID="btnAttachments" />
</li>
<li role="presentation" class="active" runat="server" id="liTracking" href="#tracking" role="tab" data-toggle="tab">
<asp:Button runat="server" ID="btnTracking" />
</li>
</ul>
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="questions">
<asp:LinkButton runat="server" ID="lbQuestions" CausesValidation="false"></asp:LinkButton>
</div>
<div role="tabpanel" class="tab-pane" id="comments">
<asp:LinkButton runat="server" ID="lbComments" OnClick="lbComments_Click"></asp:LinkButton>
</div>
<div role="tabpanel" class="tab-pane" id="attachments">
</div>
<div role="tabpanel" class="tab-pane" id="tracking">
</div>
</div>
C#
protected void Page_Load(object sender, EventArgs e)
{
lbQuestions.Click += lbComments_Click
}
...
protected void lbComments_Click(object sender, EventArgs e)
{
Console.Write("This breakpoint never gets hit");
}
Neither methods of adding the OnClick event are firing while the LinkButtons are inside of the <div class="tab-content"> div.
Oddly, asp Buttons work perfectly. However I'm unable to use the Glyphicons inside of the Buttons, or just Glyphicons as buttons themselves if I have to settle for that. -- I also need the ability to use CommandArgument/CommandName, so a simple HTML button will not suite my needs either.

The problem is likely the JS that initializes the tabs plugin. Look at that preventDefault there:
$('#myTabs a').click(function (e) {
e.preventDefault()
$(this).tab('show')
})
Consider putting a class on the buttons that you want to behave as tabs and modify your JS to the following:
$('#myTabs a.myTabbedButton').click(function (e) {
e.preventDefault()
$(this).tab('show')
})

The actual problem is in code itself..
Parser Error Message: The tag contains duplicate 'role' attributes.
Could you please check the code.
<li role="presentation" class="active" runat="server" id="liQuestions" href="#questions" role="tab" data-toggle="tab">
<asp:Button runat="server" ID="btnQuestions" />
</li>
2 role is added (role="presentation" and role="tab").
Also don't forget to add ";" after lbQuestions.Click += lbComments_Click
It works fine for me.Hope you got the issue.

Related

Bootstrap tabs showing content below previous tab

I have a webform in which i am trying to implement tabs using bootstrap 4. The content for 1st tab is shown fine but when I switch tabs the content for the second tab is shown under the previous content and the tabs dont switch. Below is my code:
<nav class="nav nav-tabs nav-justified">
<a class="nav-item nav-link active" data-toggle="tab" href="#teacher">Teacher Remarks</a>
<a class="nav-item nav-link" data-toggle="tab" href="#marks">Marks</a>
</nav>
<div class="tab-content">
<div id="teacher" role="tabpanel" class="tab-pane fade show active" aria-labelledby="teacher">
<asp:UpdatePanel id="updPnl1">
<ContentTemplate>
Content of div1
</ContentTemplate>
</asp:UpdatePanel>
</div>
<div id="marks" role="tabpanel" class="tab-pane fade show active" aria-labelledby="marks">
<asp:UpdatePanel id="updPnl2">
<ContentTemplate>
Content of div2
</ContentTemplate>
</asp:UpdatePanel>
</div>
</div>
Can someone please help? I dont understand what I am doing wrong?
You've marked both tabpanels as show active, which means they will both display by default on a page load. Try removing the show and active classes from the second div.
Edit: As per the comments below, the solution was to put the tab panel for the second tab within the first tab panel.

Giving a ListItem focus from the server on page load

On my aspx page I have the following list items/divs. Is there a way to make the tab in position 1 (divReferralTab) the selected tab on page load by referencing the div or the list item?
<div id="mainTabs" class="povMainTabs">
<ul id="ulMainTabs" runat="server">
<li id="liRDCTab" runat="server"><asp:Label runat="server" ID="lblRDC" /></li>
<li id="liReferralTab" runat="server">Referral</li>
<li id="liContactsTab" runat="server">Holistic/Contact</li>
</ul>
<div id="divRDCTab"></div>
<div id="divReferralTab"></div>
<div id="divContactsTab"></div>
</div>
If I understand you right, you can try setting the z-index of the control you need first.
https://www.w3schools.com/cssref/pr_pos_z-index.asp
If you want the referral "bullet" first then try just listing it first:
<div id="mainTabs" class="povMainTabs">
<ul id="ulMainTabs" runat="server">
<li id="liReferralTab" runat="server">Referral</li>
<li id="liRDCTab" runat="server"><asp:Label runat="server" ID="lblRDC" /></li>
<li id="liContactsTab" runat="server">Holistic/Contact</li>
</ul>
<div id="divRDCTab"></div>
<div id="divReferralTab"></div>
<div id="divContactsTab"></div>

Bootstrap 4 w/ASP.Net Nav Tabs/Pills click Opens Sub-menu and Page

I am trying to create a Bootstrap based menu replacement for a very large VS2008 ASP.NET site that uses Master Pages.
The site has a two-level menu where the top row contains main areas, and second row contains content depending upon main menu area selected. After a day, I have a nice Bootstrap layout that looks and displays secondary menu content perfectly.
Using VS 2008 (cannot update due to existing codebase),
nav and flex layout stuff with
Bootstrap.bundle js/bootstrap css v4.1.3 and JQuery 3.3.1
Where I need help is getting the main menu Nav-Pills to both Open a url to a topic page (doesn't work) - and show the nav-content submenu div if exists (works). I've cropped out a bunch of additional menus/content for the example below.
Clicking the Home Nav-Pill should show Default.aspx (already shown on load).
Home nav-Pill click screenshot:
Clicking the Nav-Search Pill should show the sub-menu AND load the Search.aspx page. Currently loads sub-menu(which will contain links to sub-area pages when done), but still shows the same page after click instead of search.aspx.
Search nav-Pill click screenshot:
Code I have so far:
MasterPage.master
<%# Master Language="C#" AutoEventWireup="true" CodeFile="MasterPage.master.cs" Inherits="MasterPage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<link href="CSS/bootstrap.css" rel="stylesheet" type="text/css" />
<link href="CSS/Site.css" rel="stylesheet" type="text/css" />
<asp:ContentPlaceHolder id="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<div class="container-fluid" style="background-color:#eeeeee">
<nav class="mainnav nav nav-pills bg-light d-flex justify-content-md-between" role="tablist">
<a class=" d-flex nav-item" href="#">
LOGO HERE<%-- <img height="44px" src="Images/logo_color.gif" alt="Logo" />--%>
</a>
<ul class="nav align-self-end">
<li class="nav-item" style="height:25px">
<%--<a class="nav-link active mr-2" id="nav-home-tab" data-toggle="tab" href="#nav-blank" role="tab" aria-controls="blank" aria-expanded="true">Home</a>--%>
<asp:HyperLink class="nav-link active mr-2" id="nav-home-tab" NavigateUrl="~/Default.aspx" data-toggle="tab" data-target="#nav-blank" role="tab" aria-controls="blank" aria-expanded="true" runat="server">Home</asp:HyperLink>
</li>
<li class="nav-item">
<%--<a class="nav-link mr-2" id="nav-search-tab" data-toggle="tab" data-target="#nav-search" href="http://google.com" role="tab" aria-controls="search" aria-expanded="true">Search</a> --%>
<asp:HyperLink class="nav-link mr-2" id="nav-search-tab" data-toggle="tab" NavigateUrl="http://google.com" data-target="#nav-search" role="tab" aria-controls="search" aria-expanded="true" runat="server">Search</asp:HyperLink>
</li>
</ul>
<div class=" d-flex d-inline-block align-content-end justify-content-end">
Admin | Help | Contact Us | Logout
</div>
</nav>
<div class="tab-content col-sm-12" id="pills-tabContent">
<div class="tab-pane fade" id="nav-blank" role="tabpanel" aria-expanded="false">
</div>
<div class="tab-pane fade" id="nav-search" role="tabpanel" aria-labelledby="nav-search-tab" aria-expanded="false">
<nav class="nav nav-tabs" id="nav-sub-search" role="tablist">
<a class="nav-item nav-link mr-2" href="#">Advanced Search</a>
<a class="nav-item nav-link mr-2" href="#">Geographical Search</a>
</nav>
</div>
</div>
</div>
<form id="form1" runat="server">
<div>
<asp:ContentPlaceHolder id="MainContent" runat="server">
</asp:ContentPlaceHolder>
</div>
</form>
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.3.1.min.js" type="text/javascript"></script>
<script src="Scripts/bootstrap.bundle.js" type="text/javascript"></script>
</body>
</html>
Home page Default.aspx
<%# Page Language="C#" MasterPageFile="~/MasterPage.Master" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<asp:Content ID="cMainContent" runat="server" ContentPlaceHolderID="MainContent">
<div class="container-fluid" style="background-color:#dddddd">
<br />
Home Page Content
</div>
</asp:Content>
Search.aspx content:
<%# Page Language="C#" MasterPageFile="~/MasterPage.Master" AutoEventWireup="true" CodeFile="Search.aspx.cs" Inherits="Search" %>
<asp:Content ID="cSearchContent" runat="server" ContentPlaceHolderID="MainContent">
<div class="container-fluid" style="background-color:#dddddd">
<br />
Search Content
</div>
</asp:Content>
I'd prefer an easy global way versus adding javascript events to every control. It almost seemed like I could use href/NavigateUrl for page name and data-target for submenu opening? - but doesn't work. Ideas?
After days I finally got it partially working with javascript written onclick events to force page load considering data-toggle="tab" destroys use of URL to open sites... and more to load submenu...
Yet - finally gave up on approach as it was too much for little effect, and it didn't support sitmap submenu hierarchy. In the end I modified sites' web.sitemap adding custom values where needed, and modifying the sites' customtheme.Skin file to support Bootstrap values. End result was being able to continue using for primary menu with autoloading of secondary submenu list. I had to add OnItemDatabound commands to mark tabs as selected (add or remove 'active' to CSS to show correct bootstrap images) when main or submenu item is selected (since main menu is not a bootstrap control).
I did find enough references to write a nice Repeater based submenu - posting here if it might help others (as most posts were single menus, this code shows how to add active/selected item support which I didn't find online):
<div class="subMenuContainer">
<asp:Repeater ID="subMenu" OnItemDataBound="subMenu_OnItemDataBound" runat="server" DataSourceID="SiteMapDataSource2">
<HeaderTemplate>
<ul class="nav nav-pills">
</HeaderTemplate>
<ItemTemplate>
<li class="nav-item">
<asp:HyperLink ID="HyperLink1" CssClass="nav-link mr-2 btn-sm btn-mycustombuttonstyle" runat="server"
Text='<%# Eval("title") %>' ToolTip='<%# Eval("description") %>' NavigateUrl='<%# Eval("Url") %>'></asp:HyperLink>
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
</div>
protected void subMenu_OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
SiteMapNode currentNode = SiteMap.CurrentNode;
if (currentNode != null)
{
HyperLink subMenuHyperlink = (HyperLink)e.Item.FindControl("HyperLink1");
string curpage = Request.Url.PathAndQuery.Substring(Request.Url.PathAndQuery.LastIndexOf('/') + 1);
string linkTarget = subMenuHyperlink.NavigateUrl.Substring(subMenuHyperlink.NavigateUrl.LastIndexOf('/') + 1);
if (linkTarget.Equals(curpage)) {
if (!subMenuHyperlink.CssClass.ToLower().Contains("active"))
{
subMenuHyperlink.CssClass += " active";
}
}
else
{
if (subMenuHyperlink.CssClass.ToLower().Contains("active"))
{
subMenuHyperlink.CssClass = subMenuHyperlink.CssClass.Replace("active", "").Trim();
}
}
}
}
}

What is the correct way to apply sr-only text to asp:LinkButtons that are variably visible?

I am working to make my code more accessible for screen-readers and I have come across this situation and have been able to find no answer for it. When buttons are only visible given a condition is met, how do you properly apply sr-only text? I want to avoid the screen-reader reading the text when the button is not visible as the button will not provide any function at that time.
The buttons are visible when paging is available (next and previous as appropriate).
Please see the attached code.
<div id="divPager" runat="server" class="gutter-bottom text-center">
<asp:UpdatePanel ID="UpdatePanel2" runat="server" UpdateMode="Conditional" RenderMode="Inline">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnSearch" EventName="ServerClick" />
</Triggers>
<ContentTemplate>
<ul class="pager">
<li>
<asp:LinkButton runat="server" ID="btnPrev" Visible="False" CommandName="PrevPage">
<i class="fa fa-arrow-left"></i> Prev
</asp:LinkButton>
</li>
<li>
<asp:LinkButton runat="server" ID="btnNext" Visible="False" CommandName="NextPage">
Next <i class="fa fa-arrow-right"></i>
</asp:LinkButton>
</li>
</ul>
</ContentTemplate>
</asp:UpdatePanel>
</div>
One thing I have considered is placing a span inside the asp:LinkButton(s) and from the code-behind conditionally adding class="sr-only" and the appropriate span-text. Am I on the right track? Is there a better way? Thanks for your input
I am posting my current solution to this problem. By no means do I think it is the best solution and I will appreciate if you take your time to show me a better way. Here is what I did on my aspx page:
<ul class="pager">
<li>
<asp:LinkButton runat="server" ID="btnPrev" Visible="False" CommandName="PrevPage">
<span id="btnPrevSR" runat="server" class="sr-only"></span>
<i class="fa fa-arrow-left"></i> Prev
</asp:LinkButton>
</li>
<li>
<asp:LinkButton runat="server" ID="btnNext" Visible="False" CommandName="NextPage">
<span id="btnNextSR" runat="server" class="sr-only"></span>
<i class="fa fa-arrow-right"></i> Next
</asp:LinkButton>
</li>
</ul>
And in my code behind
If btnPrev.Visible = True Then
btnPrevSR.InnerHtml = "Previous Page of Announcements"
End If
If btnNext.Visible = True Then
btnNextSR.InnerHtml = "Next Page of Announcements"
End If
Below is what this code looks like when generated. Notice the empty <li> because visible is set to false for btnPrev
<ul class="pager">
<li>
</li>
<li>
<a id="ctl00_ctl00_cpContent_cpContent_btnNext" href="javascript:__doPostBack('ctl00$ctl00$cpContent$cpContent$btnNext','')"><span id="ctl00_ctl00_cpContent_cpContent_btnNextSR" class="sr-only">Next Page of Announcements</span>
<i class="fa fa-arrow-right"></i> Next
</a>
</li>
</ul>

asp.net how to use list Item Clicked Event UserDetails.aspx

When the list item is clicked then i want it to redirect to
UserDetails.aspx?Id=" + Session["UserId"].ToString());
. I tryed
<li class="active "><span>Home</span></li>
But it doesnt work?
Make anchor tag runat="server" and try this
<li class="active ">
<a id="A1" runat="server" href='~/UserDetails.aspx?Id=' + <%= Session["UserId"].ToString() %>>
<span>Home</span></a></li>
<li class="active ">
<a href='<%= Page.ResolveUrl("~/UserDetails.aspx?Id=") + Session["UserId"].ToString() %>'>
Home
</a>
</li>
EDIT: Added Page.ResolveUrl and removed ';' at the end of ToString()

Resources