414 Stimmen

Wie dynamisch ändern Header basierend auf AngularJS teilweise Ansicht?

Ich verwende ng-view, um AngularJS Teilansichten einzuschließen, und ich möchte den Seitentitel und die h1-Header-Tags basierend auf der eingeschlossenen Ansicht aktualisieren. Diese sind außerhalb des Anwendungsbereichs der partiellen Ansicht-Controller aber, und so kann ich nicht herausfinden, wie man sie an Daten in den Controllern festgelegt binden.

Wenn es ASP.NET MVC wäre, könnte man @ViewBag verwenden, aber ich kenne das Äquivalent in AngularJS nicht. Ich habe über gemeinsame Dienste, Ereignisse usw. gesucht, aber immer noch nicht bekommen es funktioniert. Jede Möglichkeit, mein Beispiel zu ändern, so dass es funktioniert, wäre sehr geschätzt werden.

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"; }

32voto

Mr Hash Punkte 675

Hier ist eine angepasste Lösung, die für mich funktioniert, die nicht Injektion von $rootScope in Controllern für die Einstellung der Ressource spezifische Seitentitel erfordert.

In der Master-Vorlage:

<html data-ng-app="myApp">
    <head>
    <title data-ng-bind="page.title"></title>
    ...

In der Routing-Konfiguration:

$routeProvider.when('/products', {
    title: 'Products',
    templateUrl: '/partials/products.list.html',
    controller: 'ProductsController'
});

$routeProvider.when('/products/:id', {
    templateUrl: '/partials/products.detail.html',
    controller: 'ProductController'
});

Und im Laufblock:

myApp.run(['$rootScope', function($rootScope) {
    $rootScope.page = {
        setTitle: function(title) {
            this.title = title + ' | Site Name';
        }
    }

    $rootScope.$on('$routeChangeSuccess', function(event, current, previous) {
        $rootScope.page.setTitle(current.$$route.title || 'Default Title');
    });
}]);

Endlich im Controller:

function ProductController($scope) {
    //Load product or use resolve in routing
    $scope.page.setTitle($scope.product.name);
}

16voto

Deminetix Punkte 2668

Die Lösung von jkoreska ist perfekt, wenn Sie die Titel im Voraus kennen, aber Sie müssen den Titel möglicherweise auf der Grundlage von Daten festlegen, die Sie von einer Ressource usw. erhalten.

Meine Lösung erfordert einen einzigen Dienst. Da der rootScope die Basis aller DOM-Elemente ist, brauchen wir keinen Controller auf das html-Element zu setzen, wie jemand erwähnte

Seite.js

app.service('Page', function($rootScope){
    return {
        setTitle: function(title){
            $rootScope.title = title;
        }
    }
});

index.jade

doctype html
html(ng-app='app')
head
    title(ng-bind='title')
// ...

Alle Kontrolleure, die den Titel ändern müssen

app.controller('SomeController', function(Page){
    Page.setTitle("Some Title");
});

11voto

Alex Soroka Punkte 790

Eine saubere Art und Weise, die es erlaubt, Titel oder Meta-Beschreibung dynamisch zu setzen. Im Beispiel verwende ich ui-router, aber Sie können ngRoute auf die gleiche Weise verwenden.

var myApp = angular.module('myApp', ['ui.router'])

myApp.config(
    ['$stateProvider', function($stateProvider) {
        $stateProvider.state('product', {
            url: '/product/{id}',
            templateUrl: 'views/product.html',
            resolve: {
                meta: ['$rootScope', '$stateParams', function ($rootScope, $stateParams) {
                    var title = "Product " + $stateParams.id,
                        description = "Product " + $stateParams.id;
                    $rootScope.meta = {title: title, description: description};
                }]

                // Or using server side title and description
                meta: ['$rootScope', '$stateParams', '$http', function ($rootScope, $stateParams, $http) {
                    return $http({method: 'GET', url: 'api/product/ + $stateParams.id'})
                        .then (function (product) {
                            $rootScope.meta = {title: product.title, description: product.description};
                        });
                }]

            }
            controller: 'ProductController'
        });
    }]);

H

<!DOCTYPE html>
<html ng-app="myApp">
<head>
    <title ng-bind="meta.title + ' | My App'">myApp</title>
...

8voto

Nathan Kot Punkte 2344

Alternativ können Sie bei Verwendung von ui-router :

index.html

<!DOCTYPE html>
<html ng-app="myApp">
<head>
    <title ng-bind="$state.current.data.title || 'App'">App</title>

Weiterleitung

$stateProvider
  .state('home', {
      url: '/',
      templateUrl: 'views/home.html',
      data: {
        title: 'Welcome Home.'
      }
  }

7voto

Michael Bromley Punkte 4762

Maßgeschneiderte ereignisbasierte Lösung

Hier ist ein weiterer Ansatz, der von den anderen hier nicht erwähnt wurde (zum Zeitpunkt der Erstellung dieses Artikels).

Sie können benutzerdefinierte Ereignisse wie folgt verwenden:

// your index.html template
<html ng-app="app">
<head>
<title ng-bind="pageTitle">My App</title>

// your main app controller that is declared on the <html> element
app.controller('AppController', function($scope) {
    $scope.$on('title-updated', function(newTitle) {
        $scope.pageTitle = newTitle;
    });
});

// some controller somewhere deep inside your app
mySubmodule.controller('SomeController', function($scope, dynamicService) {
    $scope.$emit('title-updated', dynamicService.title);
});

Dieser Ansatz hat den Vorteil, dass keine zusätzlichen Dienste geschrieben und dann in jeden Controller injiziert werden müssen, der den Titel setzen muss, und dass er auch nicht die $rootScope . Außerdem können Sie einen dynamischen Titel festlegen (wie im Codebeispiel), was mit benutzerdefinierten Datenattributen im Konfigurationsobjekt des Routers nicht möglich ist (zumindest soweit ich weiß).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X