【问题标题】:MVC with Bootstrap Navbar - Set Selected Item to Active带有引导导航栏的 MVC - 将所选项目设置为活动
【发布时间】:2014-04-19 21:13:00
【问题描述】:

我正在学习 Bootstrap,无法将所选项目置于“活动”状态。活动状态保持在默认项目上。新选择/单击的项目会短暂变为活动状态,但会恢复。我已阅读所有帖子,但仍然无法使此代码正常工作。我正在使用 MVC5 和 JQuery 2.1。

编辑: 如果我将 li 的 href 更改为 href="#",则活动类将正确应用。加载新视图时会发生什么?我认为塞巴斯蒂安的反应很接近,但对区域很混乱。

标记

<div class="navbar-wrapper">
    <div class="container">
        <div class="navbar navbar-inverse navbar-fixed-top">

            <div class="navbar-header">
                <a class="navbar-toggle" data-toggle="collapse" data-target=".nav-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </a>
                <a class="navbar-brand" href="#">Test</a>
            </div>
            <div class="btn-group pull-right">
                <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
                    <i class="icon-user"></i>Login
          <span class="caret"></span>
                </a>
                <ul class="dropdown-menu">
                    <li><a href="#">Profile</a></li>
                    <li class="divider"></li>
                    <li><a href="#">Sign Out</a></li>
                </ul>
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li class="active"><a href="~/Home">Home</a></li>
                    <li><a href="~/Home/About">About</a></li>
                    <li><a href="~/Student">Students Sample</a></li>
                    <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown <b class="caret"></b></a>
                        <ul class="dropdown-menu">
                            <li><a href="~/Admin/Home/Index"">Admin</a></li>
                            <li><a href="#">Another action</a></li>
                            <li><a href="#">Something else here</a></li>
                            <li class="divider"></li>
                            <li><a href="#">Separated link</a></li>
                            <li><a href="#">One more separated link</a></li>
                        </ul>
                    </li>
                </ul>
            </div>

        </div>
    </div>
    <!-- /container -->
</div>
<!-- /navbar wrapper -->

脚本

<script type="text/javascript">

    $(function () {
        $('.navbar-nav li').click(function () {
            $(this).addClass('active').siblings().removeClass('active');
        });
    });

</script>

编辑: 这是我在发布的答案和一些研究的帮助下最终完成的工作。

public static string MakeActive(this UrlHelper urlHelper,string action, string controller, string area = "")
        {
            string result = "active";
            string requestContextRoute;
            string passedInRoute;

            // Get the route values from the request           
            var sb = new StringBuilder().Append(urlHelper.RequestContext.RouteData.DataTokens["area"]);
            sb.Append("/");
            sb.Append(urlHelper.RequestContext.RouteData.Values["controller"].ToString());
            sb.Append("/");
            sb.Append(urlHelper.RequestContext.RouteData.Values["action"].ToString());
            requestContextRoute = sb.ToString();

            if (string.IsNullOrWhiteSpace(area))
            {
                passedInRoute = "/" + controller + "/" + action;
            }
            else
            {
                passedInRoute = area + "/" + controller + "/" + action;
            }

            //  Are the 2 routes the same?
            if (!requestContextRoute.Equals(passedInRoute, StringComparison.OrdinalIgnoreCase))
            {
                result = null;
            }

            return result;
        }

【问题讨论】:

  • 您是否为这个 BigDaddy 找到了明确的解决方案?我一直想给某人打电话……特别是。汉斯·帕桑特!
  • @Killercam...看看我的编辑。它显示了我的想法。这是公认答案的扩展。

标签: asp.net-mvc twitter-bootstrap twitter-bootstrap-3


【解决方案1】:

使用代码from here 的简化版本,如果控制器和动作匹配(或者如果没有提供动作,则只标记控制器),您可以使用标签助手将锚标记为“活动”。

导航:

  <li class="nav-item px-2">
       <a class="nav-link" asp-active-route asp-controller="Home" asp-action="Index">Home</a>
  </li>
  <li class="nav-item px-2">
       <a class="nav-link" asp-active-route asp-controller="Car" asp-action="Add">Add Car</a>
   </li>

标签助手类

[HtmlTargetElement(Attributes = "asp-active-route")]
public class ActiveRouteTagHelper : TagHelper
{
    [HtmlAttributeName("asp-controller")] public string Controller { get; set; }

    [HtmlAttributeName("asp-action")] public string Action { get; set; }

    [HtmlAttributeNotBound] [ViewContext] public ViewContext ViewContext { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        if (IsActive())
        {
            output.AddClass("active", HtmlEncoder.Default);
        }

        output.Attributes.RemoveAll("asp-active-route");

        base.Process(context, output);
    }

    private bool IsActive()
    {
        var currentController = ViewContext.RouteData.Values["Controller"].ToString();
        var currentAction = ViewContext.RouteData.Values["Action"].ToString();
        var active = false;

        if (!string.IsNullOrWhiteSpace(Controller) && !string.IsNullOrWhiteSpace(currentController))
        {
            active = Controller.Equals(currentController, StringComparison.CurrentCultureIgnoreCase);

            if (active && !string.IsNullOrWhiteSpace(Action) && !string.IsNullOrWhiteSpace(currentAction))
            {
                active = Action.Equals(currentAction, StringComparison.CurrentCultureIgnoreCase);
            }
        }

        return active;
    }
}

不要忘记将标签助手添加到您的 _ViewImports.cshtml

 @addTagHelper *, My.Awesome.Web
  • 未来的改进将是检查区域并可能将整个导航包裹在控件/助手中,这样您只需比较一次路线并标记项目

【讨论】:

    【解决方案2】:

    只需添加这个 JQuery 编码:

    <script>
            $(document).ready(function () {
                $('body').find('a[href="' + location.pathname + '"]')
                    .addClass('active');
            });
    </script>
    

    【讨论】:

      【解决方案3】:

      您可以在任何视图中执行此操作

      <ul class="nav navbar-nav">
          @Html.NavigationLink("Link1", "Index", "Home")
          @Html.NavigationLink("Link2", "Index", "Home")
          @Html.NavigationLink("Link3", "Index", "Home")
          @Html.NavigationLink("Links with Parameter", "myAction", "MyController", new{ id=999}, new { @class= " icon-next" })
      </ul>
      

      将此方法添加到新类或现有 HtmlExtensions 类后

      public static class HtmlExtensions
      {
          public static MvcHtmlString NavigationLink(this HtmlHelper html, string linkText, string action, string controller, object routeValues=null, object css=null)
          {
              TagBuilder aTag = new TagBuilder("a");
              TagBuilder liTag = new TagBuilder("li");
              var htmlAttributes = HtmlHelper.AnonymousObjectToHtmlAttributes(css);
              string url = (routeValues == null)?
                  (new UrlHelper(html.ViewContext.RequestContext)).Action(action, controller)
                  :(new UrlHelper(html.ViewContext.RequestContext)).Action(action, controller, routeValues);
      
              aTag.MergeAttribute("href", url);
              aTag.InnerHtml = linkText;
              aTag.MergeAttributes(htmlAttributes);
      
              if (action.ToLower() == html.ViewContext.RouteData.Values["action"].ToString().ToLower() && controller.ToLower() == html.ViewContext.RouteData.Values["controller"].ToString().ToLower())
                  liTag.MergeAttribute("class","active");
      
              liTag.InnerHtml = aTag.ToString(TagRenderMode.Normal);
              return new MvcHtmlString(liTag.ToString(TagRenderMode.Normal));
          }
      }
      

      【讨论】:

      • 记得把@using yourNamespace放在你的视图中。就我而言,我把它放在我的视图布局_Layout.cshtml
      • 如何使用此方法进行下拉?
      【解决方案4】:

      最简单的做法是从您的控制器发送一个 ViewBag 参数,如下所示;

      public ActionResult About()
          {            
              ViewBag.Current = "About";
              return View();
          }
      
      
          public ActionResult Contact()
          {            
              ViewBag.Current = "Contact";
              return View();
          }
      

      在cshtml页面中执行以下操作;

                 <ul class="nav navbar-nav">                    
                      <li class="@(ViewBag.Current == "About" ? "active" : "")">@Html.ActionLink("About", "About", "Home")</li>
                      <li class="@(ViewBag.Current == "Contact" ? "active" : "")">@Html.ActionLink("Contact", "Contact", "Home")</li>
                  </ul>
      

      感谢@Damith here

      【讨论】:

        【解决方案5】:

        JavaScript 不工作,因为页面在运行后重新加载。所以它正确设置了活动项目,然后页面加载,因为浏览器正在跟踪链接。就个人而言,我会删除您拥有的 JavaScript,因为它没有任何用途。要执行此客户端(而不是您拥有的服务器端代码),您需要 JavaScript 在新页面加载时设置活动项。就像是:

        $(document).ready(function() {
            $('ul.nav.navbar-nav').find('a[href="' + location.pathname + '"]')
                .closest('li').addClass('active');
        });
        

        我建议您在导航栏中添加一个 id 或其他类,这样您就可以确定您选择了正确的。

        【讨论】:

        • 这就是我要找的!
        • 谢谢!但是如何将上一个菜单项恢复为原始颜色(非活动)
        • 对我来说很好用,也很简单。
        • JoshYates1980,不会有回发吗?如果不是,您可以在设置新课程之前删除所有活动课程。
        • 谢谢!这就是我要找的。所有的程序员之神都会保佑你!
        【解决方案6】:

        您的 javascript 函数应该可以正常工作...问题是您的链接路由到控制器并重新加载整个页面。为了避免这种行为,您可以将正文内容呈现为部分视图,这样导航栏元素就不会重新加载。您不必编写函数来处理 dom 事件——这就是 javascript 的用途。

        要明白我的意思,请更改您的代码:

        <li><a href="~/Home/About">About</a></li>
        <li><a href="~/Student">Students Sample</a></li>
        

        到:

         <li><a href="">About</a></li>
         <li><a href="">Students Sample</a></li>
        

        【讨论】:

          【解决方案7】:

          您必须检查您的控制器或根据当前 url 查看哪个菜单项处于活动状态:

          我有一个类似这样的扩展方法:

          public static string MakeActiveClass(this UrlHelper urlHelper, string controller)
          {
              string result = "active";
          
              string controllerName = urlHelper.RequestContext.RouteData.Values["controller"].ToString();
          
              if (!controllerName.Equals(controller, StringComparison.OrdinalIgnoreCase))
              {
                  result = null;
              }
          
              return result;
          }
          

          您可以像这样在视图中使用它:

          <!-- Make the list item active when the current controller is equal to "blog" -->
          <li class="@Url.MakeActive("blog")">
             <a href="@Url.Action("index", "blog")">....</a>
          </li>
          

          【讨论】:

          • 假设我有同名的控制器,因为它们位于区域中?
          • 在这种情况下,您还必须检查该区域。很奇怪,但是你可以使用:object areaName = urlHelper.RequestContext.RouteData.DataTokens["area"]
          • 谢谢,但应该有比这更干净的东西,对吧?
          • 我并不喜欢这个解决方案,但它似乎是做这种事情的方式 - 根据我的研究。
          • 只是一个小错字,扩展方法名应该是MakeActive而不是MakeActiveClass。
          【解决方案8】:

          我相信你的选择是倒退的。您正在添加课程,然后将其从兄弟姐妹中删除,我认为第二次删除会导致问题。您可以尝试将其反转为:

          <script type="text/javascript">
          
              $(function () {
                  $('.navbar-nav li').click(function () {
                      $(this).siblings().removeClass('active');
                      $(this).addClass('active');
                  });
              });
          
          </script>
          

          【讨论】:

          • 谢谢,但我得到了同样的行为
          • 您还有其他对导航栏起作用的事件吗?您是否可以在 jsfiddle 中重现该问题?
          • 没有其他事件。我从视图中发布所有代码。
          • 因为方法链,他的脚本和你的一样。他的问题是他的链接请求一个新页面,当页面重新加载时活动项丢失了。
          猜你喜欢
          • 2018-10-28
          • 1970-01-01
          • 2016-10-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多