Zgodnie z radą Pawła, aby użyć niestandardowej dyrektywy, oto wersja, która nie wymaga dodawania ładunku do routeConfig, jest super deklaratywna i może być dostosowana do reagowania na dowolny poziom ścieżki, po prostu zmieniając, na którą slice()
z nich zwracasz uwagę .
app.directive('detectActiveTab', function ($location) {
return {
link: function postLink(scope, element, attrs) {
scope.$on("$routeChangeSuccess", function (event, current, previous) {
/*
Designed for full re-usability at any path, any level, by using
data from attrs. Declare like this:
<li class="nav_tab">
<a href="#/home" detect-active-tab="1">HOME</a>
</li>
*/
// This var grabs the tab-level off the attribute, or defaults to 1
var pathLevel = attrs.detectActiveTab || 1,
// This var finds what the path is at the level specified
pathToCheck = $location.path().split('/')[pathLevel] ||
"current $location.path doesn't reach this level",
// This var finds grabs the same level of the href attribute
tabLink = attrs.href.split('/')[pathLevel] ||
"href doesn't include this level";
// Above, we use the logical 'or' operator to provide a default value
// in cases where 'undefined' would otherwise be returned.
// This prevents cases where undefined===undefined,
// possibly causing multiple tabs to be 'active'.
// now compare the two:
if (pathToCheck === tabLink) {
element.addClass("active");
}
else {
element.removeClass("active");
}
});
}
};
});
Osiągamy nasze cele, nasłuchując $routeChangeSuccess
wydarzenia, a nie umieszczając $watch
na ścieżce. Pracuję w przekonaniu, że to oznacza, że logika powinna działać rzadziej, ponieważ myślę, że patrzy na ogień w każdym $digest
cyklu.
Wywołaj go, przekazując argument na poziomie ścieżki w deklaracji dyrektywy. Określa, do jakiego fragmentu bieżącej $ location.path () chcesz dopasować href
atrybut.
<li class="nav_tab"><a href="#/home" detect-active-tab="1">HOME</a></li>
Tak więc, jeśli twoje karty powinny reagować na podstawowy poziom ścieżki, wprowadź argument „1”. Tak więc, gdy location.path () to „/ home”, będzie pasować do „# / home” w href
. Jeśli masz zakładki, które powinny reagować na drugi poziom, trzeci lub jedenasty odcinek ścieżki, dostosuj odpowiednio. To odcięcie od 1 lub wyższego spowoduje pominięcie nikczemnego „#” w href, który będzie miał indeks 0.
Jedynym wymaganiem jest wywołanie na <a>
elemencie an , ponieważ element zakłada obecność href
atrybutu, który będzie porównywać z bieżącą ścieżką. Jednak możesz dość łatwo dostosować się do odczytu / zapisu elementu nadrzędnego lub podrzędnego, jeśli wolisz wywołać <li>
coś takiego. Kopię to, ponieważ możesz go ponownie użyć w wielu kontekstach, po prostu zmieniając argument pathLevel. Jeśli w logice przyjęto głębokość odczytu, potrzebnych byłoby wiele wersji dyrektywy do użycia z wieloma częściami nawigacji.
EDYCJA 18.03.14: Rozwiązanie nie zostało dostatecznie uogólnione i aktywowałoby się, gdyby zdefiniowano argument dla wartości „activeTab”, który zwraca undefined
zarówno wartość „activeTab”, jak $location.path()
i wartość elementu href
. Ponieważ: undefined === undefined
. Zaktualizowano, aby naprawić ten stan.
Pracując nad tym, zdałem sobie sprawę, że powinna istnieć wersja, którą możesz po prostu zadeklarować w elemencie nadrzędnym, z taką strukturą szablonu:
<nav id="header_tabs" find-active-tab="1">
<a href="#/home" class="nav_tab">HOME</a>
<a href="#/finance" class="nav_tab">Finance</a>
<a href="#/hr" class="nav_tab">Human Resources</a>
<a href="#/quarterly" class="nav_tab">Quarterly</a>
</nav>
Zauważ, że ta wersja nie przypomina już zdalnie kodu HTML w stylu Bootstrap. Ale jest bardziej nowoczesny i zawiera mniej elementów, więc mam słabość do tego. Ta wersja dyrektywy oraz oryginał są teraz dostępne na Github jako moduł, który można po prostu zadeklarować jako zależność. Byłbym szczęśliwy mogąc je Bower-ize, gdyby ktokolwiek faktycznie ich używał.
Ponadto, jeśli chcesz mieć wersję kompatybilną z bootstrapem, która zawiera ten <li>
, możesz skorzystać z modułu Angular-ui-bootstrap Tabs , który, jak sądzę, pojawił się po tym oryginalnym poście i który jest być może nawet bardziej deklaratywny niż ten. Jest mniej zwięzły w przypadku podstawowych rzeczy, ale zapewnia dodatkowe opcje, takie jak wyłączone karty i deklaratywne zdarzenia, które uruchamiają się podczas aktywacji i dezaktywacji.