J'ai des pages statiques dans un menu de navigation. Je souhaite ajouter une classe du type "current" à l'élément en cours d'affichage.
Pour ce faire, j'ajoute des tonnes de méthodes d'assistance (chacune pour un élément) afin de contrôler le contrôleur et l'action.
def current_root_class
'class="current"' if controller_name == "homepage" && action_name == "index"
end
<ul>
<li <%= current_root_class %>><%= link_to "Home", root_path %>
Y a-t-il une meilleure façon de le faire!? Ma façon actuelle est tellement stupide ......
Ce n'est pas vraiment une réponse ici, parce que j'utilise la même chose que 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
Ensuite, vous pouvez utiliser if controller?("homepage") && action?("index", "show")
dans vos vues ou d’autres méthodes d’aide…
J'ai créé un assistant appelé 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 HTML comme
<li class="current"><a href="/">Home</a></li>
Utilisez le fichier current_page?
pour déterminer si vous devez ou non affecter 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 me lance les liens de la barre de navigation de mon navigateur Twitter 2.0.
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'ajouter une fonction d'assistance dans 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) %>
Ceci teste le chemin du lien avec la page en cours uri et retourne soit votre classe actuelle, soit une chaîne vide.
Je n'ai pas testé cela à fond et je connais très bien RoR (après une décennie d'utilisation de PHP). Si cela présente un défaut majeur, j'aimerais l'entendre.
Au moins, vous n’avez besoin que d’une fonction d’aide et d’un simple appel dans chaque lien.
Pour construire la réponse de @Skilldrick ...
Si vous ajoutez ce code à application.js, cela garantira que tous les menus déroulants avec des enfants actifs seront également marqués comme actifs ...
$('.active').closest('li.dropdown').addClass('active');
Pour récapituler du code positif> Ajoutez un utilitaire 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 HTML comme
<li class="active"><a href="/">Home</a></li>
Je sais que c'est une réponse périmée, mais vous pouvez facilement ignorer toutes ces vérifications de page en cours en utilisant un wrapper helper link_to, appelé active_link_to gem, il fonctionne exactement comme vous le souhaitez, ajoutez une classe active au lien de la page en cours.
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:
<li class="<%= is_active('controller', 'action') %>">
Voici l'exemple complet sur l'ajout d'une classe active sur la page du menu d'amorçage dans la vue Rails.
<li class="<%= 'active' if current_page?(root_path) %>"><%= link_to 'Home', controller: "welcome" %></li>
<li class="<%= 'active' if current_page?(about_path) %>"><%= link_to 'About us', about_path %></li>
<li class="<%= 'active' if current_page?(contact_path) %>"><%= link_to 'Contact us', contact_path %></li>
J'utilise un bijou génial appelé Tabs on Rails .
Pour moi personnellement, j'ai utilisé une combinaison de réponses ici
<li class="<%= 'active' if current_page?(inventory_index_path) %>"><a href="#">Menu</a></li>
J'utilise Materialise 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
La méthode current_page?
n'est pas assez souple pour moi (disons que vous définissez un contrôleur mais pas une action, alors il ne retournera que vrai sur l'action d'index du contrôleur), j'ai donc fait cela en fonction des 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 qui est personnalisée pour générer une balise li enveloppante.
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_attributes(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
"<li class=\"#{class_name}\"><a #{href_attr}#{tag_options}>#{ERB::Util.html_escape(name || url)}</a></li>".html_safe
end
end
Si vous examinez le code ci-dessus et le comparez au code link_to de 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 enveloppante. Ceci est dû au fait que j'utilise l'aide de nav_link avec le composant nav de Twitter Bootstrap, qui préfère que les liens soient placés dans des balises li et que la classe "active" soit appliquée à la liste externe.
La bonne chose à propos du code ci-dessus est qu’il vous permet de passer un bloc à la fonction, comme vous pouvez le faire avec link_to.
Par exemple, une liste de navigation bootstrap avec des icônes ressemblerait à ceci:
Svelte:
ul.nav.nav-list
=nav_link root_path do
i.icon-home
| Home
=nav_link "#" do
i.icon-user
| Users
Sortie:
<ul class="nav nav-list">
<li class="active">
<a href="/">
<i class="icon-home"/>
Home
</a>
</li>
<li>
<a href="#">
<i class="icon-users"/>
Users
</a>
</li>
</ul>
De plus, tout comme l’assistant link_to, vous pouvez passer des options HTML dans nav_link, qui sera appliqué à la balise a.
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:
<ul class="nav nav-list">
<li class="active">
<a href="/" title="Home">
<i class="icon-home"/>
Home
</a>
</li>
<li>
<a href="#" title="Users">
<i class="icon-users"/>
Users
</a>
</li>
</ul>
Laissez-moi montrer ma solution:
_header.html.erb :
<ul class="nav">
<%= nav_tabs(@tabs) %>
</ul>
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
J'utilise un assistant simple comme celui-ci pour les liens de haut niveau afin que la page /stories/my-story
mette en surbrillance le lien /stories
def nav_link text, url
active = (url == request.fullpath || (url != '/' && request.fullpath[0..(url.size-1)] == url))
"<li#{ active ? " class='selected'" : '' }><a href='#{url}'>#{text}</a></li>".html_safe
end
Oui! Découvrez cet article: Une meilleure façon d’ajouter une classe ‘sélectionnée’ aux liens dans Rails
Déposez nav_link_helper.rb dans app/helpers et cela peut être aussi simple que:
<%= nav_link 'My_Page', 'http://example.com/page' %>
L'assistant nav_link fonctionne comme l'assistant standard Rails link_to, mais ajoute une classe "sélectionnée" à 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 que celle de la page en cours, une classe par défaut de "sélectionné" est ajoutée au lien.
Il y a un Gist ici: https://Gist.github.com/3279194
UPDATE: Ceci est maintenant un joyau: http://rubygems.org/gems/nav_link_to
Cette version est basée sur celle de @ Skilldrick mais vous permet d'ajouter du contenu HTML.
Ainsi, vous pouvez faire:
nav_link "A Page", a_page_path
mais aussi:
nav_link a_page_path do
<strong>A Page</strong>
end
ou tout autre contenu HTML (vous pouvez ajouter une icône par exemple).
Ici l'aide 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_attributes(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
Selon le réponse de Skilldrick , je le changerai comme suit:
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.
Je pense avoir proposé une solution simple qui pourrait être utile dans de nombreux cas d'utilisation. Cela me permet de:
link_to
(par exemple, ajouter une icône dans le lien)application_helper.rb
active
au nom de classe entier de l'élément link au lieu d'être la classe unique.Donc, ajoutez ceci à application_helper.rb
:
def active_class?(class_name = nil, path)
class_name ||= ""
class_name += " active" if current_page?(path)
class_name.strip!
return class_name
end
Et sur votre modèle, vous pouvez avoir quelque chose comme ceci:
<div class="col-xs-3">
<%= link_to root_path, :class => active_class?("btn btn-outline-primary", root_path) do %>
<i class="fa fa-list-alt fa-fw"></i>
<% end %>
</div>
En tant que bonus, vous pouvez spécifier ou non un class_name
et l'utiliser comme ceci: <div class="<%= current_page?(root_path) %>">
Merci aux réponses précédentes 1 , 2 et ressources .
Voici comment 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
Ensuite..
li = link_to company_path
class: %w{ class_if_current_page( { status: "pending" }, "active" ), "company" } do
Current Company
Mon moyen facile -
application.html.erb
,
<div class="navbar">
<div class="<%= @menu1_current %> first-item"><a href="/menu1"> MENU1 </a></div>
<div class="<%= @menu2_current %>"><a href="/menu2"> MENU2 </a></div>
<div class="<%= @menu3_current %>"><a href="/menu3"> MENU3 </a></div>
<div class="<%= @menu4_current %> last-item"><a href="/menu4"> MENU4 </a></div>
</div>
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 le hachage des options html dans la vue. Par exemple, si vous voulez l'appeler avec une autre classe ou 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].strip!
link_to text, url, options
end
Donc, dans la vue, appelez cet assistant de la même façon que vous appelleriez 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.strip } ? "active" : ""
if class_name.present? && action_names.present?
return action_names.split(",").any? { |an| controller.action_name == an.strip } ? "active" : ""
end
class_name
end
Maintenant, utilisez-le comme indiqué ci-dessous.
1. Pour toute action d'un contrôleur spécifique
<li class="<%= active('controller_name')%>">
....
</li>
2. Pour toutes les actions de nombreux contrôleurs (séparés par une virgule)
<li class="<%= active('controller_name1,controller_name2')%>">
....
</li>
3. Pour une action spécifique d'un contrôleur spécifique
<li class="<%= active('controller_name', 'action_name')%>">
....
</li>
4. Pour l'action spécifique de nombreux contrôleurs (séparés par une virgule)
<li class="<%= active('controller_name1,controller_name2', 'action_name')%>">
....
</li>
5. Pour certaines actions spécifiques d'un contrôleur spécifique
<li class="<%= active('controller_name', 'index, show')%>">
....
</li>
6. Pour certaines actions spécifiques de nombreux contrôleurs (séparés par une virgule)
<li class="<%= active('controller_name1,controller_name2', 'index, show')%>">
....
</li>
J'espère que ça aide
tout cela fonctionne avec de simples barres de navigation, mais qu'en est-il du sous-menu déroulant? lorsqu'un sous-menu est sélectionné, l'élément du menu supérieur doit être défini comme "actuel"