Befolgen Sie die Empfehlungen von Pavel, eine benutzerdefinierte Direktive zu verwenden. Hier ist eine Version, bei der der routeConfig keine Nutzdaten hinzugefügt werden müssen. Sie ist sehr deklarativ und kann an jede Ebene des Pfads angepasst werden, indem Sie einfach ändern, auf welche slice()davon Sie achten .
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");
}
});
}
};
});
Wir erreichen unsere Ziele, indem wir auf das $routeChangeSuccessEreignis hören, anstatt ein $watchauf den Weg zu bringen. Ich arbeite unter der Überzeugung, dass dies bedeutet, dass die Logik weniger häufig ausgeführt werden sollte, da ich denke, dass Uhren bei jedem $digestZyklus feuern .
Rufen Sie es auf, indem Sie Ihr Argument auf Pfadebene für die Direktivendeklaration übergeben. Dies gibt an, mit welchem Teil des aktuellen $ location.path () Sie Ihr hrefAttribut abgleichen möchten .
<li class="nav_tab"><a href="#/home" detect-active-tab="1">HOME</a></li>
Wenn Ihre Registerkarten auf die Basisebene des Pfads reagieren sollen, geben Sie das Argument '1' ein. Wenn location.path () "/ home" ist, stimmt es mit dem "# / home" in der href. Wenn Sie Registerkarten haben, die auf die zweite oder dritte oder elfte Ebene des Pfads reagieren sollen, passen Sie sie entsprechend an. Dieses Schneiden von 1 oder höher umgeht das schändliche '#' in der href, das bei Index 0 leben wird.
Die einzige Voraussetzung ist, dass Sie ein aufrufen <a>, da das Element das Vorhandensein eines hrefAttributs voraussetzt , das mit dem aktuellen Pfad verglichen wird. Sie können sich jedoch relativ leicht anpassen, um ein übergeordnetes oder untergeordnetes Element zu lesen / schreiben, wenn Sie das <li>oder etwas aufrufen möchten. Ich grabe dies, weil Sie es in vielen Kontexten wiederverwenden können, indem Sie einfach das Argument pathLevel variieren. Wenn die zu lesende Tiefe in der Logik angenommen wurde, benötigen Sie mehrere Versionen der Direktive, um sie mit mehreren Teilen der Navigation zu verwenden.
EDIT 18.03.14: Die Lösung wurde nicht ausreichend verallgemeinert und wird aktiviert, wenn Sie ein Argument für den Wert von 'activeTab' definieren, das undefinedsowohl für beide $location.path()als auch für das Element zurückgegeben wird href. Weil : undefined === undefined. Aktualisiert, um diesen Zustand zu beheben.
Während ich daran arbeitete, wurde mir klar, dass es eine Version geben sollte, die Sie einfach für ein übergeordnetes Element deklarieren können, mit einer Vorlagenstruktur wie dieser:
<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>
Beachten Sie, dass diese Version nicht mehr im entferntesten Stil HTML im Bootstrap-Stil ähnelt. Aber es ist moderner und verwendet weniger Elemente, also bin ich parteiisch. Diese Version der Direktive sowie das Original sind jetzt auf Github als Drop-In-Modul verfügbar, das Sie einfach als Abhängigkeit deklarieren können. Ich würde sie gerne bower-ize, wenn jemand sie tatsächlich benutzt.
Wenn Sie eine Bootstrap-kompatible Version wünschen, die <li>'s' enthält , können Sie auch das Angular-UI-Bootstrap-Tabs-Modul verwenden , das meiner Meinung nach nach diesem ursprünglichen Beitrag herausgekommen ist und das vielleicht sogar noch aussagekräftiger ist als dieses. Es ist weniger prägnant für grundlegende Dinge, bietet Ihnen jedoch einige zusätzliche Optionen, wie deaktivierte Registerkarten und deklarative Ereignisse, die beim Aktivieren und Deaktivieren ausgelöst werden.