Make Bootstrap tabs active on MVC action - html

I want the tab to be set to active once I click on that tab (action). However, the issue I am experiencing is that the "Dashboard" tab is always set to active
<div class="row top-buffer">
<ul class="nav nav-tabs">
<li class="active">#Html.ActionLink("Dashboard", "Index")</li>
<li>#Html.ActionLink("Users", "Users")</li>
<li>#Html.ActionLink("Investigator Groups", "Groups")</li>
<li>#Html.ActionLink("Assign Games", "AssignGames")</li>
<li>#Html.ActionLink("Reports", "Reports")</li>
</ul>
</div>
Edit:
I tried doing the following, which now allows the tabs to be set to active, but no longer redirects to the action.
<li class="active" data-toggle="tab">#Html.ActionLink("Dashboard", "Index")</li>
<li data-toggle="tab">#Html.ActionLink("Users", "Users")</li>

follow this tutorial Setting the active menu item in a MVC C# Bootstrap application
by adding an extension method
public static class HtmlHelpers
{
public static string IsActive(this HtmlHelper htmlHelper, string action, string controller)
{
var routeData = htmlHelper.ViewContext.RouteData;
var routeAction = routeData.Values["action"].ToString();
var routeController = routeData.Values["controller"].ToString();
var returnActive = (controller == routeController && action == routeAction);
return returnActive ? "active" : "";
}
}
and then use it
<li class="#Html.IsActive("Index", "Dashboard")">#Html.ActionLink("Dashboard", "Index")</li>
<li class="#Html.IsActive("Users", "Users")">#Html.ActionLink("Users", "Users")</li>

Related

How to change active list item in typescript

I have some list items which are treated as Tabs in my UI. I also have a 'next' button under every tab and last tab have a 'finish' button. I need to move to next tab when i clicked on 'Next' button. I am working on an Angular2 project with typescript version 2.3.4. So i need some typescript code to work on button click.
While searching, i got some jquery code like,
$('.nav-tabs > .active').next('li').find('a') from how to display next bootstrap tab on button click.
I tried it in my button click(.ts file) and it works!. But i am not sure about the using of jquery in my project. Is it possible to get the element(html) in its typescript file? Or is this is the good possible way to do this?
My list is like,
<div class="row">
<ul class="nav nav-tabs bg-white">
<li class="active"><a data-toggle="tab" href="#BasicInfo">BasicInfo</a></li>
<li id="idAddInfoTab"><a data-toggle="tab" href="#AdditionalInfo">AdditionalInfo</a></li>
<li id="idPlayerIdentity" class="active-border"><a data-toggle="tab" href="#PlayerIdentity">PlayerIdentity</a></li>
</ul>
</div>
Thanks in advance!
I would do something like this
page.ts
//declare 3 variables
isT1Active:boolean = true;
isT2Active:boolean = false;
isT3Active:boolean = false;
...
activate(elem){
//deactivate all first
this.isT1Active = false;
this.isT2Active = false;
this.isT3Active = false;
switch(elem){
case 't1':{this.isT1Active = true;break;}
case 't2':{this.isT2Active = true;break;}
case 't3':{this.isT3Active = true;break;}
}
}
page.html
<div class="row">
<ul class="nav nav-tabs bg-white">
<li [ngClass]="{'active': isT1Active}" (click)="activate("t1")"><a data-toggle="tab" href="#BasicInfo">BasicInfo</a></li>
<li [ngClass]="{'active': isT2Active}" (click)="activate("t2")" id="idAddInfoTab"><a data-toggle="tab" href="#AdditionalInfo">AdditionalInfo</a></li>
<li [ngClass]="{'active': isT3Active}" (click)="activate("t3")" id="idPlayerIdentity" class="active-border"><a data-toggle="tab" href="#PlayerIdentity">PlayerIdentity</a></li>
</ul>
</div>
And you can do same thing to the next button, In assume that each tab will have a next button
I would stay away from jQuery, but instead learn how to better use Angular to control the view. Basically, you want the active class in your template tab to be bound to your component selected model, so that when the selected model is updated, Angular will automatically apply the active class to the matching tab.
In your component, define the array that stores the tab info and define a selectedTab that refers to the specific tab that should be active:
export class AppComponent {
tabs = [
{id:'idBasicInfo', href:'...',label:'BasicInfo'},
{id:'idAddInfo', href:'...',label:'AdditionalInfo'},
{id:'idPlayerIdentity',href:'...',label:'PlayerIdentity'}
];
selectedTab = this.tabs[0]; // which is active by default
}
Then in your template, use these properties to drive the view:
<ul>
<li *ngFor="let t of tabs" [id]="t.id" [class.active]="t===selectedTab">
<a data-toggle="tab" [href]="t.href" (click)="selectedTab=t"> {t.label}} </a>
</li>
</ul>
When a tab is clicked, it will be made the selectedTab and its active class will be set.

Angular [attr.href] condition with ng-click

I have an Angular5 application with a bootstrap tab control. I set the href of a tab to # if the property modelChanged is true, otherwise I set it to #tab1 (or #tab2):
<ul class="nav nav-tabs">
<li class="active">
<a (click)="changeTab()" [attr.href]="modelChanged ? '#':'#tab1'" data-toggle="tab">Tab 1</a>
</li>
<li>
<a (click)="changeTab()" [attr.href]="modelChanged ? '#':'#tab2'" data-toggle="tab">Tab 2</a>
</li>
</ul>
So basically I am able to change the tab if modelChanged is set to false, othwerise not.
Now I wan't to use a function called changeTab() where I change the modelChanged property to false and would expect that the tab change from 1 to 2 but it doesn't until I click the tab again:
changeTab() {
modelChanged = false;
}
Anyone knows a solution for that?
Sorry that I don't have a working plunker but I think some of you will be able to answer my question anyway.
2 ways to do the same
1) in your click specify modelChanged = !modelChanged,
[click]="modelChanged = !modelChanged"
2) [click]="modelChanged = changeTab()"
and in your controller specify the changeTab function like this
function changeTab(){
//do something
return false;
}

ASP.NET MVC - Reg Menu item in nav with Authentication

I am new to MVC world. I have a nav in my Layout file used by logged in users :
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>#Html.ActionLink("Home", "Index", "Member")</li>
<li>#Html.ActionLink("My Profile", "MyProfile", "Member")</li>
<!-- User type Admin, then Admin Menu -->
<li>#Html.ActionLink("Admin Index", "AdminIndex", "Member")</li>
<li>#Html.ActionLink("About", "About", "Home")</li>
<!-- Throws error /User/Logout not found -->
<li>#Html.ActionLink("Logout", "Logout", "User")</li>
<!-- Works Perfectly fine, but the link is on new line & different font/color/underlined -->
#if (Request.IsAuthenticated)
{
using (Html.BeginForm("Logout", "User", FormMethod.Post, new { id = "logoutForm" }))
{
<li>Logout</li>
}
}
</ul>
</div>
The #Html.ActionLink("Logout" doesn't work. It throws "/User/Logout" not found Error How to make that work like the below logout with <a href ??? Is the error b'coz in href, their is form and calling Form.Post method ??
Controller code :
public class UserController : Controller
{
// Registeration Action
[HttpGet]
public ActionResult Registeration() {..... }
// Login
[HttpGet]
public ActionResult Login() {.... }
// Login Post
[HttpPost]
public ActionResult Login(UserLogin userLogin, string returnUrl) { ...}
// Logout
[Authorize]
[HttpPost]
public ActionResult Logout()
{
FormsAuthentication.SignOut();
return RedirectToAction("Login", "User");
}
}
Can anyone please help me get this work !! Any help is highly appreciated.
Thanks
I suspect, although it is difficult to tell, that the controller is not UserController but maybe AccountController (the default) or MemberController.
In which case the call should be
#Html.ActionLink("Logout", "Logout", "Account")
or
#Html.ActionLink("Logout", "Logout", "Member")
Following your additional edit I think the issue will be that logout is a Post and a link is only ever a Get request so Mvc is looking for a get action /User/logout. There is an answer here about how to convert a link to a Post here.
I would probably get your link to call an ajax command in some js code. To make the most of the Razor goodness you can use #Url.Action. Alter your code as follows.
Your nav will look like this;
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>#Html.ActionLink("Home", "Index", "Member")</li>
<li>#Html.ActionLink("My Profile", "MyProfile", "Member")</li>
<!-- User type Admin, then Admin Menu -->
<li>#Html.ActionLink("Admin Index", "AdminIndex", "Member")</li>
<li>#Html.ActionLink("About", "About", "Home")</li>
<li>Log Out</li>
}
}
</ul>
</div>
Then your javascript function needs to be somewhere accessible to your nav page (the bottom of your _Layout page is probably easiest).
<script type="text/javascript">
function LogOut() {
$.ajax({
type: "POST",
url: "#Url.Action("Logout", "User")"
});
}
</script>
Hope that makes sense, I haven't tested it but your link should now look like all the others and your controller will now be getting a POST request so will access your logout method. Any problems shout.

Umbraco 6 razor menu

Hi I want to add a class of "active" to my li, if it is active or if I am on a page under that. I have the following code
#inherits Umbraco.Web.Mvc.UmbracoTemplatePage
#{
Layout = null;
}
<nav class="topNav">
<ul>
#foreach (var item in Model.Content.AncestorOrSelf(1).Children.Where(x => x.IsVisible() && x.IsDocumentType("Subfrontpage") || x.IsDocumentType("Procesguide")))
{
<li>
#item.Name
</li>
}
</ul>
</nav>
I think I can do something with this, but it gives an error
var isSelected = Model.Path.Contains(item.Id.ToString()) ? "active" : "";
<li class="#Html.Raw(isSelected)">
#item.Name
</li>
This is the error I get. Line 10.
Compilation Error
Description: An error occurred during the compilation of a resource required to service this request. Please review the following specific error details and modify your source code appropriately.
Compiler Error Message: CS1061: 'Umbraco.Web.Models.RenderModel' does not contain a definition for 'Path' and no extension method 'Path' accepting a first argument of type 'Umbraco.Web.Models.RenderModel' could be found (are you missing a using directive or an assembly reference?)
Source Error:
Line 8: #foreach (var item in Model.Content.AncestorOrSelf(1).Children.Where(x => x.IsVisible() && x.IsDocumentType("Subfrontpage") || x.IsDocumentType("Procesguide")))
Line 9: {
Line 10: var isSelected = Model.Path.Contains(item.Id.ToString()) ? "active" : "";
Line 11:
Line 12: <li class="#Html.Raw(isSelected)">
I have now tried with this, but no lunk
<ul>
<li>
#home.Name
</li>
#foreach (var item in Model.Content.AncestorOrSelf(1).Children.Where(x => x.IsVisible() && x.IsDocumentType("Subfrontpage") || x.IsDocumentType("Procesguide")))
{
var isSelected = item.IsDescendant(Model,"active", "");
<li class="#Html.Raw(isSelected)">
#item.Name
</li>
}
</ul>
ok here is the solution. This is for typed, not dynamic cshtml.
#inherits Umbraco.Web.Mvc.UmbracoTemplatePage
#{
Layout = null;
var home = Model.Content.AncestorOrSelf(1);
}
<ul>
#*Render Home item*#
#{ var homeActive = ""; }
#if( home.Id == Model.Content.Id){
homeActive = "active";
}
<li class="#homeActive">
<a href="#home.Url">
#home.Name
</a>
</li>
#*Render Home children*#
#foreach (var item in home.Children.Where(x => x.IsVisible()))
{
var active = "";
if(home.Id != Model.Content.Id){ #* if NOT home *#
if (item.Id == Model.Content.AncestorOrSelf(2).Id){
#* if foreach id and currentpage ancestor id is equal *#
active = "active";
}
}
<li class="#active">
<a href="#item.Url">
#item.Name
</a>
</li>
}
</ul>
You can try something like this:
var isSelected = item.IsDescendant(Model,"active", "");
Here is a list of the functions you can use:
#Model.AncestorOrSelf(string nodeTypeAlias)
#Model.AncestorOrSelf(int level)
#Model.AncestorOrSelf(Func<DynamicNode, bool> func)
and those Helper functions:
#Model.IsDescendant(DynamicNode[,valueIfTrue][,valueIfFalse])
#Model.IsDescendantOrSelf(DynamicNode[,valueIfTrue][,valueIfFalse])
Reference: Is the current page a descendant of a specific node id?
The following is the default script for navigation produced by umbraco:
#inherits umbraco.MacroEngines.DynamicNodeContext
#*
Macro to display child pages below the root page of a standard website.
Also highlights the current active page/section in the navigation with
the css class "current".
*#
#{
#*Get the root of the website *#
var root = Model.AncestorOrSelf(1);
}
<ul>
#foreach (var page in root.Children.Where("Visible"))
{
<li class="#page.IsAncestorOrSelf(Model, "current", "")">
#page.Name
</li>
}
</ul>
I just created a menu myself and needed the Home page to be active also. Working with just the method IsAncestorOrSelf doesn't work for the homepage.
The piece of code I've created is this:
#{
var root = Model.AncestorOrSelf(1);
var homeClass = root.Id == Model.Id ? "active" : "";
}
<ul id="nav" class="nav navbar-nav pull-right">
<li class="#homeClass"><a href="/" >Home</a></li>
#foreach (var page in root.Children.Where("Visible"))
{
<li class="#page.IsAncestorOrSelf(Model, "active", "")">
#page.Name
</li>
}
</ul>
This iterates through all children of the root node (1). To be able to discover if you are on the Home page, I'm checking the Id's of the page and set the active class accordingly.

DRY approach to Razor syntax marking the currently viewed tab of a web page

I have some tabs at the top of a web page: home, features, contact, etc.
I need the category I am currently on to be marked as .
How can I appropriately code my _Layout.cshtml page with razor syntax so that I don't have to manually mark each page's appropriate tab as class="current" ?
<li class="current">#Html.ActionLink("Home", "Index", "Home")
<li>#Html.ActionLink("Blog", "Blog", "Home")
<li>#Html.ActionLink("Portfolio", "Portfolio", "Home")
Example way you could do it.
#helper BuildLink(string name, string action, string controller)
{
var url = Url.Action(action, controller);
bool isActive = Request.Url.AbsolutePath.Equals(url, StringComparison.InvariantCultureIgnoreCase);
<li class="#(isActive ? "current" : String.Empty)">#name</li>
}
#BuildLink("Home", "Index", "Home")
#BuildLink("Blog", "Blog", "Home")
#BuildLink("Portfolio", "Portfolio", "Home")
you can set on each controller ViewData["Home"] = "activeTab" class, and use that information in the view.
This will make the tab active if the value of that viewData dictionary is taken.
Is simple and very clean.
Inside controller set viewdata like this
ViewData["SomeTab"] = "activeTab";
return View("Index");
View side:
<li class="<# ((string)ViewData["SomeTab"] ?? "") >"><#Html.ActionLink("SomeTab", "Index", "Home")></li>
<li class="<# ((string)ViewData["MyPage"] ?? "") %>"><#Html.ActionLink("MyPage", "MyPage", "")></li>