I am currently looking to add a CSS class if a page is active. What is the best way to do this in Phoenix currently? Is there a helper for this case?
def active(option, conn) do
if option == conn.request_path do
" class=\"active\""
else
""
end
end
In the template:
<%= "contact" |> active(@conn) |> raw %>
To select elements with a specific class, write a period (.) character, followed by the name of the class. You can also specify that only specific HTML elements should be affected by a class. To do this, start with the element name, then write the period (.)
If you want to use a class, use a full stop (.) followed by the class name in a style block. Next, use a bracket called a declaration block that contains the property to stylize the element, such as text color or text size. CSS Classes will help you stylize HTML elements quickly.
Yes you can - first capture the event using onmouseover , then set the class name using Element. className . If you like to add or remove classes - use the more convenient Element. classList method.
We'll use conn.path_info
which returns the current path as a list of strings instead of conn.request_path
. We could use that to get in our active_class
helper.
def active_class(conn, path) do
current_path = Path.join(["/" | conn.path_info])
if path == current_path do
"active"
else
nil
end
end
Then we use it like:
<%= link "Users", to: user_path(@conn, :index), class: active_class(@conn, user_path(@conn, :index))%>
Note that we user_path/2
twice above. We could DRY that up with another helper:
def active_link(conn, text, opts) do
class = [opts[:class], active_class(conn, opts[:to])]
|> Enum.filter(& &1)
|> Enum.join(" ")
opts = opts
|> Keyword.put(:class, class)
link(text, opts)
end
Why use conn.path_info
instead of conn.request_path
? This is because conn.request_path
will return the exact path the user requested. If user visits path /foo/
, then conn.request_path
will return /foo/
. The problem with that is the router helper we will compare to will always return a path /foo
without the trailing /
.
Hope that helps! Let me know if anything is unclear.
I have created a helper for this that looks like:
defmodule LinkHelper
@doc """
Calls `active_link/3` with a class of "active"
"""
def active_link(conn, controllers) do
active_link(conn, controllers, "active")
end
@doc """
Returns the string in the 3rd argument if the expected controller
matches the Phoenix controller that is extracted from conn. If no 3rd
argument is passed in then it defaults to "active".
The 2nd argument can also be an array of controllers that should
return the active class.
"""
def active_link(conn, controllers, class) when is_list(controllers) do
if Enum.member?(controllers, Phoenix.Controller.controller_module(conn)) do
class
else
""
end
end
def active_link(conn, controller, class) do
active_link(conn, [controller], class)
end
end
I then import this in the def view
function inside of web/web.ex
def view do
...
import LinkHelper
...
end
Usage:
<li class="<%= active_link(@conn, PageController)%>"><a href="<%= page_path(@conn, :index) %>">Home</a></li>
<li class="<%= active_link(@conn, [FooController, BarController])%>"><a href="<%= foo_path(@conn, :index) %>">Foo or Bar</a></li>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With