Meilleure façon d’append la classe «actuelle» à la navigation dans Rails 3

J’ai des pages statiques dans un menu de navigation. Je veux append une classe comme “current” à l’élément en cours d’affichage.

La façon dont je le fais est d’append des tonnes de méthodes d’aide (chacune pour un élément) pour vérifier le contrôleur et l’action.

def current_root_class 'class="current"' if controller_name == "homepage" && action_name == "index" end 
    <li >

Y a-t-il un meilleur moyen de le faire !? Ma façon actuelle est tellement stupide ……

Pas vraiment une réponse ici, parce que j’utilise tout comme vous. Je viens de définir des méthodes d’assistance pour tester plusieurs contrôleurs ou actions:

Dans application_helper.rb

  def controller?(*controller) controller.include?(params[:controller]) end def action?(*action) action.include?(params[:action]) end 

Vous pouvez ensuite utiliser if controller?("homepage") && action?("index", "show") dans vos vues ou autres méthodes d’aide…

J’ai fait une aide appelée nav_link :

 def nav_link(link_text, link_path) class_name = current_page?(link_path) ? 'current' : '' content_tag(:li, :class => class_name) do link_to link_text, link_path end end 

utilisé comme:

 nav_link 'Home', root_path 

qui produira du HTML comme

 
  • Home
  • Utilisez la page en cours current_page? aide pour déterminer si vous devez ou non atsortingbuer la classe "current" . Par exemple:

     <%= 'active' if current_page?(home_about_path) %> 

    Notez que vous pouvez également passer un chemin (pas seulement un hachage d’options), par exemple: current_page?(root_path) .

    J’utilise cette fonction nav_link (text, link) dans application_helper.rb (Rails 3) pour faire le travail et lance mes liens de barre de navigation twitter 2.0 bootstrap pour moi.

     def nav_link(text, link) recognized = Rails.application.routes.recognize_path(link) if recognized[:controller] == params[:controller] && recognized[:action] == params[:action] content_tag(:li, :class => "active") do link_to( text, link) end else content_tag(:li) do link_to( text, link) end end end 

    Exemple:

     <%=nav_link("About Us", about_path) %> 

    La façon dont je l’ai fait est d’append une fonction d’aide dans l’application_helper

     def current_class?(test_path) return 'current' if request.request_uri == test_path '' end 

    Puis dans le nav,

     <%= link_to 'Home', root_path, :class => current_class?(root_path) %> 

    Cela teste le chemin de liaison sur la page en cours et renvoie soit votre classe actuelle, soit une chaîne vide.

    Je n’ai pas testé cela de manière approfondie et je suis très nouveau sur RoR (passer à autre chose après une décennie avec PHP), alors si cela présente un défaut majeur, j’aimerais l’entendre.

    Au moins de cette manière, vous n’avez besoin que d’une fonction d’assistant et d’un appel simple dans chaque lien.

    Pour construire la réponse de @Skilldrick …

    Si vous ajoutez ce code à application.js, il s’assurera que tous les menus déroulants avec enfants actifs seront également marqués comme actifs …

     $('.active').closest('li.dropdown').addClass('active'); 

    Pour récapituler le code de soutien> Ajouter un assistant appelé nav_link:

     def nav_link_to(link_text, link_path) class_name = current_page?(link_path) ? 'active' : '' content_tag(:li, :class => class_name) do link_to link_text, link_path end end 

    utilisé comme:

     nav_link_to 'Home', root_path 

    qui produira du HTML comme

     
  • Home
  • Je pense que le meilleur moyen est

    application_helper.rb:

     def is_active(controller, action) params[:action] == action && params[:controller] == controller ? "active" : nil end 

    Et dans le menu:

     
  • Je sais que c’est une réponse obsolète, mais vous pouvez facilement ignorer toutes ces vérifications de la page en utilisant un wrapper link_to helper, appelé active_link_to gem, cela fonctionne exactement comme vous voulez, append une classe active au lien de la page en cours

    Voici l’exemple complet sur l’ajout d’une classe active sur la page de menu bootstrap dans la vue des rails.

      
  • <%= link_to 'Home', controller: "welcome" %>
  • <%= link_to 'About us', about_path %>
  • <%= link_to 'Contact us', contact_path %>
  • J’utilise un bijou génial appelé Tabs on Rails .

    La page en cours current_page? La méthode n’est pas assez flexible pour moi (disons que vous définissez un contrôleur mais pas une action, alors cela retournera seulement vrai sur l’action d’index du contrôleur), donc je l’ai fait en me basant sur les autres réponses:

      def nav_link_to(link_text, link_path, checks=nil) active = false if not checks.nil? active = true checks.each do |check,v| if not v.include? params[check] active = false break end end end return content_tag :li, :class => (active ? 'active' : '') do link_to link_text, link_path end end 

    Exemple:

     nav_link_to "Pages", pages_url, :controller => 'pages' 

    J’ai une version plus succincte de nav_link qui fonctionne exactement comme link_to, mais est personnalisée pour produire une balise li liant.

    Mettez ce qui suit dans votre application_helper.rb

     def nav_link(*args, &block) if block_given? options = args.first || {} html_options = args.second nav_link(capture(&block), options, html_options) else name = args[0] options = args[1] || {} html_options = args[2] html_options = convert_options_to_data_atsortingbutes(options, html_options) url = url_for(options) class_name = current_page?(url) ? 'active' : nil href = html_options['href'] tag_options = tag_options(html_options) href_attr = "href=\"#{ERB::Util.html_escape(url)}\"" unless href "
  • #{ERB::Util.html_escape(name || url)}
  • ".html_safe end end

    Si vous regardez le code ci-dessus et le comparez au code link_to dans url_helper.rb, la seule différence est qu’il vérifie si l’URL est la page en cours et ajoute la classe “active” à une balise li encapsulante. C’est parce que j’utilise l’assistant nav_link avec le composant nav de Twitter Bootstrap qui préfère que les liens soient encapsulés dans les balises li et la classe “active” appliquée au li externe.

    La bonne chose à propos du code ci-dessus est qu’il vous permet de passer un bloc dans la fonction, comme vous pouvez le faire avec link_to.

    Par exemple, une liste de navigation bootstrap avec des icons ressemblerait à ceci:

    Svelte:

     ul.nav.nav-list =nav_link root_path do i.icon-home | Home =nav_link "#" do i.icon-user | Users 

    Sortie:

      

    De plus, tout comme l’assistant link_to, vous pouvez passer des options HTML dans nav_link, qui seront appliquées à la balise.

    Un exemple de passage dans un titre pour l’ancre:

    Svelte:

     ul.nav.nav-list =nav_link root_path, title:"Home" do i.icon-home | Home =nav_link "#", title:"Users" do i.icon-user | Users 

    Sortie:

      

    Oui! Consultez cet article: Une meilleure façon d’append une classe “sélectionnée” aux liens dans Rails

    Déposez nav_link_helper.rb dans l’application / helpers et cela peut être aussi simple que:

     <%= nav_link 'My_Page', 'http://example.com/page' %> 

    L’aide nav_link fonctionne exactement comme l’assistant link_to standard de Rails, mais ajoute une classe ‘selected’ à votre lien (ou à son wrapper) si certains critères sont remplis. Par défaut, si l’URL de destination du lien est la même URL que l’URL de la page en cours, une classe par défaut de «sélectionné» est ajoutée au lien.

    Il y a un aperçu ici: https://gist.github.com/3279194

    MISE À JOUR: Ceci est maintenant un joyau: http://rubygems.org/gems/nav_link_to

    J’utilise un assistant simple comme celui-ci pour les liens de haut niveau afin que la page /stories/my-story souligne le lien /stories

     def nav_link text, url active = (url == request.fullpath || (url != '/' && request.fullpath[0..(url.size-1)] == url)) "#{text}".html_safe end 

    Laissez-moi vous montrer ma solution:

    _header.html.erb :

       

    application_helper.rb :

      def nav_tabs(tabs=[]) html = [] tabs.each do |tab| html << (content_tag :li, :class => ("current-page" if request.fullpath.split(/[\??]/)[0] == tab[:path]) do link_to tab[:path] do content_tag(:i, '', :class => tab[:icon]) + tag(:br) + "#{tab[:name]}" end end) end html.join.html_safe end 

    application_controller.rb :

     before_filter :set_navigation_tabs private def set_navigation_tabs @tabs = if current_user && manager? [ { :name => "Home", :icon => "icon-home", :path => home_index_path }, { :name => "Portfolio", :icon => "icon-camera", :path => portfolio_home_index_path }, { :name => "Contact", :icon => "icon-envelope-alt", :path => contact_home_index_path } ] elsif current_user && client? ... end 

    Personnellement, j’ai utilisé une combinaison de réponses ici

     
  • Menu
  • J’utilise matérialiser css et ma façon de rendre les principales catégories réductibles est d’utiliser le code ci-dessous

     $('.active').closest(".collapsible.collapsible-accordion") .find(".collapsible-header") .click(); 

    j’espère que ça aide quelqu’un

    Selon la réponse de Skilldrick , je vais changer ceci:

     def nav_link(*args, &block) is_active = current_page?(args[0]) || current_page?(args[1]) class_name = is_active ? 'active' : nil content_tag(:li, class: class_name) do link_to *args, &block end end 

    pour le rendre beaucoup plus utile.

    Cette version est basée sur celle de @ Skilldrick mais vous permet d’append du contenu HTML.

    Ainsi, vous pouvez faire:

    nav_link "A Page", a_page_path

    mais aussi:

     nav_link a_page_path do A Page end 

    ou tout autre contenu HTML (vous pouvez append une icône par exemple).

    Ici, l’assistant est:

      def nav_link(name = nil, options = nil, html_options = nil, &block) html_options, options, name = options, name, block if block_given? options ||= {} html_options = convert_options_to_data_atsortingbutes(options, html_options) url = url_for(options) html_options['href'] ||= url class_name = current_page?(url) ? 'current' : '' content_tag(:li, :class => class_name) do content_tag(:a, name || url, html_options, &block) end end 

    Je pense que j’ai trouvé une solution simple qui pourrait être utile pour beaucoup de cas d’utilisation. Cela me permet:

    • link_to charge non seulement le texte brut, mais le code HTML dans link_to (par exemple, append une icône dans le lien)
    • Ajoutez juste quelques lignes de code à application_helper.rb
    • Ajouter active au nom de classe entier de l’élément de lien au lieu d’être la seule classe.

    Donc, ajoutez ceci à application_helper.rb :

     def active_class?(class_name = nil, path) class_name ||= "" class_name += " active" if current_page?(path) class_name.ssortingp! return class_name end 

    Et sur votre modèle, vous pouvez avoir quelque chose comme ceci:

     
    <%= link_to root_path, :class => active_class?("btn btn-outline-primary", root_path) do %> <% end %>

    En bonus, vous pouvez spécifier ou non un nom de class_name et l’utiliser comme ceci:

    Merci aux réponses précédentes 1 , 2 et aux ressources .

    tout cela fonctionne avec des barres de navigation simples, mais qu’en est-il du sous-menu déroulant? lorsqu’un sous-menu est sélectionné, l’élément de menu supérieur doit être mis à jour dans ce cas tabs_on_rails moi être la solution

    C’est comme ça que j’ai résolu mon projet actuel.

     def class_if_current_page(current_page = {}, *my_class) if current_page?(current_page) my_class.each do |klass| "#{klass} " end end end 

    Alors..

     li = link_to company_path class: %w{ class_if_current_page( { status: "pending" }, "active" ), "company" } do Current Company 

    Mon moyen facile –

    application.html.erb ,

      

    main_controller.erb ,

     class MainController < ApplicationController def menu1 @menu1_current = "current" end def menu2 @menu2_current = "current" end def menu3 @menu3_current = "current" end def menu4 @menu4_current = "current" end end 

    Merci.

    Si vous souhaitez également prendre en charge les options html dans la vue. Par exemple, si vous voulez l’appeler avec une autre classe ou un autre identifiant CSS, vous pouvez définir la fonction d’assistance comme ceci.

     def nav_link_to(text, url, options = {}) options[:class] ||= "" options[:class] += " active" options[:class].ssortingp! link_to text, url, options end 

    Donc, dans la vue, appelez cette aide de la même façon que vous appelez link_to helper

     <%= nav_link_to "About", about_path, class: "my-css-class" %> 

    Créez une méthode dans ApplicationHelper comme ci-dessous.

     def active controllers, action_names = nil class_name = controllers.split(",").any? { |c| controller.controller_name == c.ssortingp } ? "active" : "" if class_name.present? && action_names.present? return action_names.split(",").any? { |an| controller.action_name == an.ssortingp } ? "active" : "" end class_name end 

    Maintenant, utilisez-le dans les cas d’utilisation ci-dessous.

    1. Pour toute action d’un contrôleur spécifique

     
  • ....
  • 2. Pour toutes les actions de plusieurs contrôleurs (avec virgule séparée)

     
  • ....
  • 3. Pour une action spécifique de tout contrôleur spécifique

     
  • ....
  • 4. Pour l’action spécifique de nombreux contrôleurs (avec virgule séparée)

     
  • ....
  • 5. Pour certaines actions spécifiques d’un contrôleur spécifique

     
  • ....
  • 6. Pour certaines actions spécifiques de plusieurs contrôleurs (avec virgule séparée)

     
  • ....
  • J’espère que cela aide