Ich verwende ng-view, um AngularJS-Teilansichten einzuschließen, und ich möchte den Seitentitel und die h1-Header-Tags basierend auf der enthaltenen Ansicht aktualisieren. Diese liegen jedoch außerhalb des Bereichs der Teilansichts-Controller, und daher kann ich nicht herausfinden, wie sie an den Datensatz in den Controllern gebunden werden.
Wenn es ASP.NET MVC wäre, könnten Sie @ViewBag verwenden, um dies zu tun, aber ich kenne das Äquivalent in AngularJS nicht. Ich habe nach gemeinsam genutzten Diensten, Ereignissen usw. gesucht, kann es aber immer noch nicht zum Laufen bringen. Jede Möglichkeit, mein Beispiel so zu ändern, dass es funktioniert, wäre sehr dankbar.
Mein HTML:
<html data-ng-app="myModule">
<head>
<!-- include js files -->
<title><!-- should changed when ng-view changes --></title>
</head>
<body>
<h1><!-- should changed when ng-view changes --></h1>
<div data-ng-view></div>
</body>
</html>
Mein JavaScript:
var myModule = angular.module('myModule', []);
myModule.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/test1', {templateUrl: 'test1.html', controller: Test1Ctrl}).
when('/test2', {templateUrl: 'test2.html', controller: Test2Ctrl}).
otherwise({redirectTo: '/test1'});
}]);
function Test1Ctrl($scope, $http) { $scope.header = "Test 1";
/* ^ how can I put this in title and h1 */ }
function Test2Ctrl($scope, $http) { $scope.header = "Test 2"; }
Antworten:
Sie können den Controller auf der
<html>
Ebene definieren.Sie erstellen einen Service:
Page
und ändern ihn über Controller.Injizieren
Page
und rufen Sie 'Page.setTitle ()' von Controllern auf.Hier ist das konkrete Beispiel: http://plnkr.co/edit/0e7T6l
quelle
$rootScope
anstatt einen zusätzlichen Controller zu erstellen.Ich habe gerade eine gute Möglichkeit gefunden, Ihren Seitentitel festzulegen, wenn Sie Routing verwenden:
JavaScript:
HTML:
Bearbeiten : Verwenden Sie das
ng-bind
Attribut anstelle von Locken,{{}}
damit sie beim Laden nicht angezeigt werdenquelle
title = "Blog"
aber nicht einstellentitle = '{{"Blog post " + post.title}}'
.current.title
auchcurrent.$route
den alten Code verwendet und er hat funktioniert. Mit dem Upgrade wird die doppelte $ on-Route benötigt.current.$$route
'/Product/:id'
. Gibt es eine Möglichkeit, den:id
Wert mit dieser Methode zu haben? Ich habe es versucht,title: function(params){return params.id;}
aber es funktioniert nicht ... Vielleicht mitresolve
?Beachten Sie, dass Sie den Titel auch direkt mit Javascript festlegen können, dh
Dies hat keine Datenbindung, aber es reicht aus, wenn das Einfügen
ng-app
des<html>
Tags problematisch ist. (Verwenden Sie beispielsweise JSP-Vorlagen, bei denen<head>
genau an einer Stelle definiert ist, Sie jedoch mehr als eine App haben.)quelle
Das Deklarieren
ng-app
deshtml
Elements bietet den Stammbereich für dashead
undbody
.Injizieren Sie daher in Ihrem Controller
$rootScope
eine Header-Eigenschaft und legen Sie diese fest:und auf Ihrer Seite:
quelle
document.title = "App"
.Das Modul anglejs-viewhead zeigt einen Mechanismus zum Festlegen des Titels pro Ansicht, wobei nur eine benutzerdefinierte Direktive verwendet wird.
Es kann entweder auf ein vorhandenes Ansichtselement angewendet werden, dessen Inhalt bereits der Ansichtstitel ist:
... oder es kann als eigenständiges Element verwendet werden. In diesem Fall ist das Element im gerenderten Dokument unsichtbar und wird nur zum Festlegen des Ansichtstitels verwendet:
Der Inhalt dieser Direktive wird im Stammbereich als verfügbar gemacht
viewTitle
, sodass er wie jede andere Variable für das title-Element verwendet werden kann:Es kann auch an jeder anderen Stelle verwendet werden, die den Stammbereich "sehen" kann. Zum Beispiel:
Mit dieser Lösung kann der Titel über denselben Mechanismus festgelegt werden, mit dem der Rest der Präsentation gesteuert wird: AngularJS-Vorlagen. Dies vermeidet die Notwendigkeit, Steuerungen mit dieser Präsentationslogik zu überladen. Der Controller muss alle Daten zur Verfügung stellen, die zur Information des Titels verwendet werden. Die Vorlage entscheidet jedoch endgültig, wie sie dargestellt werden soll, und kann Ausdrucksinterpolation und Filter verwenden, um wie gewohnt an Bereichsdaten zu binden.
(Haftungsausschluss: Ich bin der Autor dieses Moduls, verweise hier jedoch nur in der Hoffnung, dass es jemand anderem hilft, dieses Problem zu lösen.)
quelle
Hier ist eine angepasste Lösung, die für mich funktioniert und keine Injektion von $ rootScope in Controller zum Festlegen ressourcenspezifischer Seitentitel erfordert.
In der Master-Vorlage:
In der Routing-Konfiguration:
Und im Laufblock:
Endlich in der Steuerung:
quelle
$rootScope.page.setTitle(current.$$route.title || current.$$route.controller.replace('Ctrl', ''));
this.title = title.replace('<', '<').replace('>', '>').replace(' & ', ' & ') + ' | Site Name';
Die Lösung von jkoreska ist perfekt, wenn Sie die Titel vorher kennen, aber Sie müssen den Titel möglicherweise basierend auf Daten festlegen, die Sie von einer Ressource usw. erhalten.
Meine Lösung erfordert einen einzigen Dienst. Da das rootScope die Basis aller DOM-Elemente ist, müssen wir dem HTML-Element keinen Controller hinzufügen, wie dies bereits erwähnt wurde
Page.js
index.jade
Alle Controller, die den Titel ändern müssen
quelle
{{title}}
Verwendenng-bind='title'
ng-bind
verhindert , dass die vorinterpolierte Syntax angezeigt wird , bevor der Titel tatsächlich ausgewertet wird. +100Eine saubere Methode, mit der Titel oder Meta-Beschreibungen dynamisch festgelegt werden können. In Beispiel verwende ich UI-Router, aber Sie können ngRoute auf die gleiche Weise verwenden.
HTML:
quelle
Alternativ, wenn Sie einen UI-Router verwenden :
index.html
Routing
quelle
ui-router
Aktualisierung der URL und des Inhalts basierend auf meinem Status und erhalte keine Fehler oder Warnungen, aber ich kann scheinbar nicht über einen Teil des Statuskonfigurationsobjekts darauf zugreifen$state.current.[...]
. Mit welcher Versionui-router
haben Sie dies getan?Benutzerdefinierte ereignisbasierte Lösung
Hier ist ein anderer Ansatz, der von den anderen hier nicht erwähnt wurde (zum Zeitpunkt dieses Schreibens).
Sie können benutzerdefinierte Ereignisse wie folgt verwenden:
Dieser Ansatz hat den Vorteil, dass keine zusätzlichen Dienste geschrieben und dann in jeden Controller eingefügt werden müssen, der den Titel festlegen muss, und dass er auch nicht (ab) verwendet
$rootScope
. Sie können damit auch einen dynamischen Titel festlegen (wie im Codebeispiel), der mit benutzerdefinierten Datenattributen für das Konfigurationsobjekt des Routers nicht möglich ist (zumindest soweit ich weiß).quelle
In Szenarien, in denen Sie keine ngApp haben, die das
title
Tag enthält , fügen Sie Controllern, die den Fenstertitel festlegen müssen, einfach einen Dienst hinzu.Arbeitsbeispiel ... http://jsfiddle.net/8m379/1/
quelle
Wenn Sie keine Kontrolle über das Titelelement haben (wie das asp.net-Webformular), können Sie Folgendes verwenden
quelle
Einfache und schmutzige Art und Weise mit
$rootScope
:Wenn Sie in Ihren Controllern über die zum Erstellen des Titels erforderlichen Daten verfügen, gehen Sie wie folgt vor:
quelle
Keine dieser Antworten schien intuitiv genug zu sein, deshalb habe ich eine kleine Anweisung erstellt, um dies zu tun. Auf diese Weise können Sie den Titel auf der Seite dort deklarieren, wo dies normalerweise der Fall ist, und er kann auch dynamisch sein.
Sie müssen natürlich den Modulnamen ändern, um ihn an Ihren anzupassen.
Um es zu verwenden, werfen Sie dies einfach in Ihre Ansicht, ähnlich wie Sie es für ein normales
<title>
Tag tun würden :Sie können auch nur einfachen Text einfügen, wenn Sie dies nicht benötigen:
Alternativ können Sie ein Attribut verwenden, um es IE-freundlicher zu machen:
Sie können natürlich jeden gewünschten Text in das Tag einfügen, einschließlich Angular-Code. In diesem Beispiel wird nach dem
$scope.titleText
Controller gesucht, in dem sich das benutzerdefinierte Titel-Tag gerade befindet.Stellen Sie nur sicher, dass Ihre Seite nicht mehrere Seitentitel-Tags enthält, da sie sich sonst gegenseitig überladen.
Plunker-Beispiel hier http://plnkr.co/edit/nK63te7BSbCxLeZ2ADHV . Sie müssen die Zip-Datei herunterladen und lokal ausführen, um die Titeländerung zu sehen.
quelle
html
. In meiner Direktive füge ich auch eine optionalepageTitlePrefix
Konstante ein.Einfache Lösung für Angular-UI-Router:
HTML:
App.js> myApp.config-Block
App.js> myApp.run
quelle
Hier ist eine andere Möglichkeit, Titeländerungen vorzunehmen. Vielleicht nicht so skalierbar wie eine Factory-Funktion (die möglicherweise unbegrenzte Seiten verarbeiten kann), aber es war für mich einfacher zu verstehen:
In meiner index.html habe ich so angefangen:
Dann habe ich einen Teil namens "nav.html" gemacht:
Dann ging ich zurück zu "index.html" und fügte die nav.html mit ng-include und der ng-view für meine Partials hinzu:
Beachten Sie, dass ng-Mantel? Es hat nichts mit dieser Antwort zu tun, aber es verbirgt die Seite, bis sie geladen ist , eine nette Geste :) Erfahren Sie hier, wie: Angularjs - ng-cloak / ng-show-Elemente blinken
Hier ist das Grundmodul. Ich habe es in eine Datei namens "app.js" eingefügt:
Wenn Sie gegen Ende des Moduls schauen, werden Sie feststellen, dass ich eine Critter-Detail-Seite habe, die auf: id basiert. Es ist ein Teil, der auf der Crispy Critters-Seite verwendet wird. [Blöd, ich weiß - vielleicht ist es eine Seite, auf der alle Arten von Hühnernuggets gefeiert werden;) Wie auch immer, Sie können den Titel aktualisieren, wenn ein Benutzer auf einen beliebigen Link klickt. Dort würde das $ root.title-Update hingehen, genau wie Sie es in der obigen Datei nav.html gesehen haben:
Tut mir leid, aber ich bevorzuge einen Beitrag, der genügend Details enthält, um ihn zum Laufen zu bringen. Beachten Sie, dass die Beispielseite in den AngularJS-Dokumenten veraltet ist und eine Version 0.9 der ng-bind-Vorlage zeigt. Sie können sehen, dass es nicht so viel anders ist.
Nachgedacht: Sie wissen das, aber es ist für alle anderen da; Am Ende der index.html muss die Datei app.js im Modul enthalten sein:
quelle
Als ich das lösen musste, konnte ich das nicht
ng-app
auf demhtml
Tag der Seite platzieren , also habe ich es mit einem Service gelöst:quelle
Benutzerdefinierte ereignisbasierte Lösung, inspiriert von Michael Bromley
Ich konnte es nicht mit $ scope zum Laufen bringen, also habe ich es mit rootScope versucht, vielleicht etwas schmutziger ... (insbesondere, wenn Sie eine Aktualisierung auf der Seite vornehmen, die das Ereignis nicht registriert)
Aber ich mag die Idee wirklich, wie die Dinge lose miteinander verbunden sind.
Ich benutze anglejs 1.6.9
index.run.js
anyController.controller.js
index.html
Es funktioniert für mich :)
quelle
Während andere möglicherweise bessere Methoden haben, konnte ich $ rootScope in meinen Controllern verwenden, da jede meiner Ansichten / Vorlagen einen eigenen Controller hat. Sie müssen das $ rootScope in jeden Controller injizieren. Das ist vielleicht nicht ideal, aber es funktioniert für mich, also dachte ich, ich sollte es weitergeben. Wenn Sie die Seite überprüfen, wird die ng-Bindung zum Titel-Tag hinzugefügt.
Beispiel Controller:
Beispiel für einen Index.html-Header:
Sie können pageTitle und pageDescription auch auf dynamische Werte setzen, z. B. die Rückgabe von Daten aus einem REST-Aufruf:
Auch hier haben andere vielleicht bessere Ideen, wie sie dies angehen sollen, aber da ich ein Pre-Rendering verwende, werden meine Anforderungen erfüllt.
quelle
Vielen Dank an tosh shimayama für seine Lösung.
Ich dachte, es wäre nicht so sauber, einen Dienst direkt in den Dienst zu stellen
$scope
. Deshalb hier meine geringfügige Variation: http://plnkr.co/edit/QJbuZZnZEDOBcYrJXWWsDer Controller (der mir in der ursprünglichen Antwort etwas zu dumm erschien) erstellt ein ActionBar-Objekt, das in $ scope gestopft ist.
Das Objekt ist für die tatsächliche Abfrage des Dienstes verantwortlich. Es ist auch versteckt aus dem $ Rahmen der Aufruf der Vorlage URL zu setzen, die stattdessen an andere Steuerungen verfügbar ist , um die URL zu setzen.
quelle
Herr Hash hatte bisher die beste Antwort, aber die folgende Lösung macht sie (für mich) ideal, indem sie die folgenden Vorteile hinzufügt:
Im Router:
Im Laufblock:
quelle
Die bessere und dynamischere Lösung, die ich gefunden habe, besteht darin, $ watch zu verwenden, um die Variablenänderungen zu verfolgen und dann den Titel zu aktualisieren.
quelle