2015-07-22 3 views
10

В настоящее время я ищу, чтобы добавить класс CSS, если страница активна. Каков наилучший способ сделать это сейчас в Финиксе? Есть ли помощник для этого случая?Применить класс CSS на элемент, если текущая страница в Phoenix

def active(option, conn) do 
    if option == conn.request_path do 
    " class=\"active\"" 
    else 
    "" 
    end 
end 

В шаблоне:

<%= "contact" |> active(@conn) |> raw %> 

ответ

4

Я создал помощника для этого, что выглядит следующим образом:

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 

я затем импортировать это в функции def view внутри web/web.ex

def view do 
    ... 
    import LinkHelper 
    ... 
end 

Использование:

<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> 
+0

Это кажется хорошим выбором для интеграции в систему Controller. Некоторые проблемы с вашим примером кода. 'defmodule LinkHelper do' и' import LinkHelper' – rockerBOO

+0

@rockerBOO хорошее место - должно быть, забыл обновить импорт, когда я его скопировал! – Gazler

+0

Разве этот подход не устанавливает ссылку на «активную» для всех действий контроллера, которые вы передаете ему? Например, 'page_path (@conn,: index)' и 'page_path (@conn,: show)' оба будут установлены как активные, если вы передадите 'PageController' в' active_link/3'. Разве мы не хотим, чтобы страница показа была «активной», только если мы находимся на странице. Show? – Gjaldon

15

Мы будем использовать conn.path_info, которая возвращает текущий путь в виде списка строк, вместо conn.request_path. Мы могли бы использовать это, чтобы попасть в наш помощник active_class.

def active_class(conn, path) do 
    current_path = Path.join(["/" | conn.path_info]) 
    if path == current_path do 
    "active" 
    else 
    nil 
    end 
end 

Тогда мы используем его как:

<%= link "Users", to: user_path(@conn, :index), class: active_class(@conn, user_path(@conn, :index))%> 

Обратите внимание, что мы user_path/2 в два раза выше. Мы могли бы СУХОЙ, что с другим помощником:

def active_link(conn, path, opts) do 
    class = [opts[:class], active_class(conn, path)] 
      |> Enum.filter(& &1) 
      |> Enum.join(" ") 
    opts = opts 
     |> Keyword.put(:class, class) 
     |> Keyword.put(:to, path) 
    link text, opts 
end 

Почему conn.path_info вместо conn.request_path? Это связано с тем, что conn.request_path вернет точный путь, который запросил пользователь. Если пользователь посещает путь /foo/, то conn.request_path вернет /foo/. Проблема с этим - помощник маршрутизатора, который мы будем сравнивать, всегда будет возвращать путь /foo без заднего /.

Надеюсь, что это поможет! Дайте мне знать, если что-то неясно.

+0

Это кажется довольно понятным и довольно простым, и работает с путями напрямую. 'conn.request_path' находится в 0.15 master на github прямо сейчас, но не в <0.15. – rockerBOO

+0

@rockerBOO ты прав. Он находится в мастер-плагине. Пробовал это, но я все же предлагаю использовать 'conn.path_info'. Я обновлю ответ, почему – Gjaldon

+0

Очень полезно, но переменная 'text' не определена. –

Смежные вопросы