Làm cách nào để thay đổi động tiêu đề dựa trên chế độ xem một phần AngularJS?


411

Tôi đang sử dụng ng-view để bao gồm các chế độ xem một phần AngularJS và tôi muốn cập nhật tiêu đề trang và thẻ tiêu đề h1 dựa trên chế độ xem được bao gồm. Mặc dù vậy, chúng nằm ngoài phạm vi của bộ điều khiển xem một phần và vì vậy tôi không thể tìm ra cách liên kết chúng với bộ dữ liệu trong bộ điều khiển.

Nếu đó là ASP.NET MVC, bạn có thể sử dụng @ViewBag để làm điều này, nhưng tôi không biết tương đương trong AngularJS. Tôi đã tìm kiếm về các dịch vụ được chia sẻ, các sự kiện, v.v. nhưng vẫn không thể làm cho nó hoạt động. Bất kỳ cách nào để sửa đổi ví dụ của tôi để nó hoạt động sẽ được đánh giá cao.

HTML của tôi:

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

JavaScript của tôi:

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

Nhận xét này có thể muộn nhưng tôi muốn thêm. cssfacts.com/simple-dynamic-meta-tags-in-angularjs Điều này có thể hữu ích cho việc thiết lập các metas động. Bạn sẽ chỉ thay đổi biến meta $ rootScope của bạn.
Kamuran Sönecek

Câu trả lời:


342

Bạn có thể xác định bộ điều khiển ở <html>cấp độ.

 <html ng-app="app" ng-controller="titleCtrl">
   <head>
     <title>{{ Page.title() }}</title>
 ...

Bạn tạo dịch vụ: Pagevà sửa đổi từ bộ điều khiển.

myModule.factory('Page', function() {
   var title = 'default';
   return {
     title: function() { return title; },
     setTitle: function(newTitle) { title = newTitle }
   };
});

Tiêm Pagevà gọi 'Page.setTitle ()' từ bộ điều khiển.

Dưới đây là ví dụ cụ thể: http://plnkr.co/edit/0e7T6l


11
uhmm ... Tôi không chắc chắn nếu đặt một dịch vụ thẳng vào phạm vi $ được coi là tốt đẹp trong kiến ​​trúc AngularJS. Có lẽ tốt hơn là đặt trong phạm vi $ một hàm Trình điều khiển và sau đó để hàm này truy vấn dịch vụ.
superjos

11
Ví dụ này thật tuyệt vời. Mặc dù vậy, tôi có một lượt theo dõi, khi tải ban đầu, bạn có thể thấy văn bản {{Page.title ()}} trong tiêu đề (rất nhanh). Tôi không nghĩ bạn có thể sử dụng ng-cloak vì nó không có trong cơ thể. Bất kỳ đề nghị để tránh điều này?
Arthur Frankel

52
@ArthurFrankel Chỉ cần sử dụng ng-bind (ví dụ ng-bind = "Page.title ()")
Pius Uzamere

2
hoặc chúng tôi có thể chỉ định bộ điều khiển trong thẻ tiêu đề, không cần bộ điều khiển toàn cầu trên tiêu đề html: <title ng-controller = "titleCtrl"> {{Page.title ()}} </ title>
Dmitri Algazin

6
Cá nhân tôi thích đặt tiêu đề $rootScopethay vì tạo một bộ điều khiển bổ sung.
DDA

634

Tôi vừa phát hiện ra một cách hay để đặt tiêu đề trang của bạn nếu bạn đang sử dụng định tuyến:

JavaScript:

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

myApp.config(
    ['$routeProvider', function($routeProvider) {
        $routeProvider.when('/', {
            title: 'Home',
            templateUrl: '/Assets/Views/Home.html',
            controller: 'HomeController'
        });
        $routeProvider.when('/Product/:id', {
            title: 'Product',
            templateUrl: '/Assets/Views/Product.html',
            controller: 'ProductController'
        });
    }]);

myApp.run(['$rootScope', function($rootScope) {
    $rootScope.$on('$routeChangeSuccess', function (event, current, previous) {
        $rootScope.title = current.$$route.title;
    });
}]);

HTML:

<!DOCTYPE html>
<html ng-app="myApp">
<head>
    <title ng-bind="'myApp &mdash; ' + title">myApp</title>
...

Chỉnh sửa : sử dụng ng-bindthuộc tính thay vì curlies {{}}để chúng không hiển thị khi tải


11
đúng, nhưng ví dụ của bạn không chỉ ra cách thay đổi tiêu đề trên $ routeChangeSuccess được tham số hóa bởi các biến $ scope, ví dụ của @ tosh sử dụng dịch vụ Trang. Vì vậy, bạn có thể thiết lập title = "Blog"nhưng không title = '{{"Blog post " + post.title}}'.
Eric Drechsel

10
@felix bạn có thể truy cập vào tiêu đề như current.titlecũng
Eldelshell

8
$ rootScope.title = hiện tại. $ route.title; không doble $$
david.sansay

7
Tôi vừa nâng cấp phiên bản Angular của mình một số phiên bản (1.0.5 lên 1.2.7) và điều này đã phá vỡ tôi trong mã của tôi. Tôi đã sử dụng current.$routemã cũ và nó đã hoạt động. Với việc nâng cấp, cần tăng gấp đôi $ trên tuyến. current.$$route
Tyler Forsythe

6
Trong câu trả lời khi có thể nhìn thấy '/Product/:id'. Có cách nào để có :idgiá trị với phương pháp này không? Tôi đã thử title: function(params){return params.id;}nhưng không hoạt động ... Có thể sử dụng resolve?
mickaelb91

190

Lưu ý rằng bạn cũng có thể đặt tiêu đề trực tiếp bằng javascript, nghĩa là

$window.document.title = someTitleYouCreated;

Điều này không có ràng buộc dữ liệu, nhưng nó đủ khi đặt ng-appvào <html>thẻ có vấn đề. (Ví dụ: sử dụng các mẫu JSP <head>được xác định ở một nơi chính xác, nhưng bạn có nhiều hơn một ứng dụng.)


5
Đây là cách duy nhất để làm cho nó hoạt động trên Internet Explorer đối với tôi, các phương thức khác hoạt động trên các trình duyệt khác
Maarten

4
Như Maarten đã đề cập, đây là cách tiếp cận duy nhất hoạt động trong eg7 và eg8
cướp

33
Thật ngạc nhiên khi mọi người không thể lùi lại và xem điều này có thể được thực hiện dễ dàng như thế nào nếu không có phạm vi và nhà máy
redben

7
Không thể tin được. Điều này đơn giản hơn nhiều so với tất cả các shenanigans mà người khác đang đề cập. Cảm ơn!
Leonard Teo

8
Sử dụng 'cửa sổ' đơn giản là ổn - điều đó trực tiếp tác động lên DOM. '$ window' là một thứ góc cạnh và bạn phải tiêm nó để sử dụng nó. Một trong hai cách sẽ làm việc.
broc.seib

119

Khai báo ng-apptrên htmlphần tử cung cấp phạm vi gốc cho cả headbody.

Do đó, trong trình điều khiển của bạn tiêm $rootScopevà đặt thuộc tính tiêu đề vào đây:

function Test1Ctrl($rootScope, $scope, $http) { $rootScope.header = "Test 1"; }

function Test2Ctrl($rootScope, $scope, $http) { $rootScope.header = "Test 2"; }

và trong trang của bạn:

<title ng-bind="header"></title>

8
câu trả lời tốt nhất theo ý kiến ​​của tôi. Để có một bộ điều khiển ở cấp ng-app như được mô tả trong câu trả lời được chấp nhận là vô ích trong trường hợp này.
Nicolas Janel

1
Tôi thích giải pháp này nhẹ như thế nào và nó tránh sử dụng các thuộc tính $$
tedwards947

Câu trả lời được chấp nhận thêm các biến chứng và rủi ro không cần thiết. Phiên bản này làm cho nó đơn giản như thiết lập một biến.
Special0ne

3
Nếu bạn đã chết khi sử dụng $ rootScope, tôi ít nhất sẽ trích xuất điều này cho một dịch vụ để bạn không có $ rootScope trong bộ điều khiển của mình.
Michael J. Calkins

3
Tôi muốn sử dụng giải pháp này nhưng tôi tò mò không biết những lợi thế của việc sử dụng nó là gì document.title = "App";
lại

43

Các mô-đun angularjs-viewhead hiển thị một cơ chế để đặt tiêu đề trên cơ sở mỗi lượt xem chỉ bằng một lệnh tùy chỉnh.

Nó có thể được áp dụng cho một thành phần khung nhìn hiện có có nội dung đã là tiêu đề khung nhìn:

<h2 view-title>About This Site</h2>

... hoặc nó có thể được sử dụng như một phần tử độc lập, trong trường hợp đó phần tử sẽ ẩn đi trong tài liệu được hiển thị và sẽ chỉ được sử dụng để đặt tiêu đề chế độ xem:

<view-title>About This Site</view-title>

Nội dung của lệnh này được cung cấp trong phạm vi gốc như viewTitlevậy, vì vậy nó có thể được sử dụng trên thành phần tiêu đề giống như bất kỳ biến nào khác:

<title ng-bind-template="{{viewTitle}} - My Site">My Site</title>

Nó cũng có thể được sử dụng ở bất kỳ vị trí nào khác có thể "nhìn thấy" phạm vi gốc. Ví dụ:

<h1>{{viewTitle}}</h1>

Giải pháp này cho phép đặt tiêu đề thông qua cùng một cơ chế được sử dụng để kiểm soát phần còn lại của bản trình bày: các mẫu AngularJS. Điều này tránh sự cần thiết phải làm lộn xộn các bộ điều khiển với logic trình bày này. Bộ điều khiển cần cung cấp bất kỳ dữ liệu nào sẽ được sử dụng để thông báo tiêu đề, nhưng mẫu đưa ra quyết định cuối cùng về cách trình bày nó và có thể sử dụng phép nội suy biểu thức và bộ lọc để liên kết với dữ liệu phạm vi như bình thường.

(Tuyên bố miễn trừ trách nhiệm: Tôi là tác giả của mô-đun này, nhưng tôi chỉ tham khảo nó ở đây với hy vọng nó sẽ giúp người khác giải quyết vấn đề này.)


4
Không thể tin rằng giải pháp này đã không được nâng cao hơn nữa. Hầu hết những người khác là sự lựa chọn thiết kế thực sự xấu.
Martin Wawrusch

Đồng ý, đây nên là giải pháp hàng đầu. Tôi thích điều này tốt hơn nhiều so với việc khai báo một bộ điều khiển ở cấp độ trang để đặt tiêu đề. FYI: sử dụng cái này với Angular v1.3.2 và angular-route-Seg v1.3.3 và nó hoạt động như một bùa mê.
Nate Barbettini

Tôi tán thành giải pháp này;)
jkoreska

3
Tôi đã viết thêm một chút về angularjs-viewhead và một ý tưởng liên quan khác ở đây trên blog của tôi:
Martin Atkins

Nếu sử dụng lại cùng một chế độ xem ở cấp cao nhất và ở chế độ xem cấp dưới, người ta vẫn có thể sử dụng tiêu đề chế độ xem với ng-if, ví dụ: <h4 ng-if = "$ state.includes ('some-state')" view-title> Chi tiết cho {{...}} </ h4> <h4 ng-if = "! $ state.includes ('some-state')"> Chi tiết cho {{...}} </ h4 >
anre

32

Đây là một giải pháp phù hợp với tôi mà không yêu cầu tiêm $ rootScope vào các bộ điều khiển để đặt tiêu đề trang cụ thể cho tài nguyên.

Trong mẫu chính:

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

Trong cấu hình định tuyến:

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

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

Và trong khối chạy:

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');
    });
}]);

Cuối cùng trong bộ điều khiển:

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

1
Tập hợp danh hiệu trong ProductController ($ scope.page.setTitle) đang được ghi đè bởi $ rootScope $ trên ( '$ routeChangeSuccess' Thiết lập một tiêu đề mặc định trong $ rootScope $ trên ( '$ routeChangeStart' là an toàn hơn trong lĩnh vực này....
Kristo Aun

@ mr-hash: đây là điều chỉnh nhỏ tôi đề xuất, hoàn hảo cho các dự án góc cạnh hiện có với nhiều tuyến đường, nhưng không có tiêu đề. Nó sẽ tạo tiêu đề từ tên của bộ điều khiển, nếu không có tiêu đề nào được xác định trên tuyến đường:$rootScope.page.setTitle(current.$$route.title || current.$$route.controller.replace('Ctrl', ''));
mikhail-t

1
nhớ vệ sinh đầu ra như thế này:this.title = title.replace('<', '&lt;').replace('>', '&gt;').replace(' & ', ' &amp; ') + ' | Site Name';
Henrik Stenbæk

Tôi đã nhận được lỗi không xác định vì vậy tôi đã thay đổi bit cuối cùng thành: $ rootScope.page.title = current. $$ tuyến đường? hiện tại. $$ tuyến.title + '| Tên trang web ':' Tên trang web ';
Andy

15

Giải pháp của jkoreska là hoàn hảo nếu bạn biết trước các tiêu đề, nhưng bạn có thể cần đặt tiêu đề dựa trên dữ liệu bạn nhận được từ tài nguyên, v.v.

Giải pháp của tôi yêu cầu một dịch vụ duy nhất. Vì rootScope là cơ sở của tất cả các thành phần DOM, nên chúng ta không cần đặt bộ điều khiển trên phần tử html như ai đó đã đề cập

Trang.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')
// ...

Tất cả các bộ điều khiển cần thay đổi tiêu đề

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

một vấn đề nhỏ, khi bạn làm mới một trang, trong tên tab của bạn, bạn sẽ thấy '{{title}}' và sau khi trang được hiển thị, bạn chỉ thấy 'Một số Tiêu đề'. giải pháp với nhà máy không có hành vi đó
Dmitri Algazin

5
thay vì {{title}}sử dụngng-bind='title'
Faradox 7/8/2015

1
Đồng ý với @Faradox ... sử dụng ng-bindngăn cú pháp được nội suy trước hiển thị trước khi tiêu đề thực sự đánh giá. +100
Seth

11

Một cách rõ ràng cho phép tự động thiết lập tiêu đề hoặc mô tả meta. Ví dụ tôi sử dụng ui-router nhưng bạn có thể sử dụng ngRoute theo cách tương tự.

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'
        });
    }]);

HTML:

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

8

Ngoài ra, nếu bạn đang sử dụng ui-router :

index.html

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

định tuyến

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

2
Tôi không thể làm việc này .. Tôi đã ui-routercập nhật URL và nội dung dựa trên trạng thái của mình và tôi không gặp lỗi hay cảnh báo nào, nhưng dường như tôi không thể truy cập bất kỳ phần nào của đối tượng cấu hình trạng thái thông qua $state.current.[...]. Phiên bản ui-routernào bạn đã sử dụng để làm điều này?

Chỉnh sửa "Cấu hình thời gian chạy" của tôi để trả lời giải quyết vấn đề tôi đã đề cập trong nhận xét của mình ở trên. :) Tôi mở ý tưởng nếu có cách tốt hơn để làm điều này mặc dù.

điều này không hiệu quả với tôi và 'tiêu đề' không được tìm thấy trong các tài liệu API - điều này có còn được hỗ trợ không?
GraehamF

7

Giải pháp dựa trên sự kiện tùy chỉnh

Đây là một cách tiếp cận khác chưa được đề cập bởi những người khác ở đây (như bài viết này).

Bạn có thể sử dụng các sự kiện tùy chỉnh như vậy:

// 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);
});

Cách tiếp cận này có ưu điểm là không yêu cầu các dịch vụ bổ sung được viết và sau đó được đưa vào mọi bộ điều khiển cần đặt tiêu đề và cũng không (ab) sử dụng $rootScope. Nó cũng cho phép bạn đặt tiêu đề động (như trong ví dụ mã), không thể sử dụng các thuộc tính dữ liệu tùy chỉnh trên đối tượng cấu hình của bộ định tuyến (theo như tôi biết ít nhất).


5

Đối với các tình huống mà bạn không có ngApp có chứa titlethẻ, chỉ cần đưa dịch vụ vào bộ điều khiển cần đặt tiêu đề cửa sổ.

var app = angular.module('MyApp', []);

app.controller('MyController', function($scope, SomeService, Title){
    var serviceData = SomeService.get();
    Title.set("Title of the page about " + serviceData.firstname);
});

app.factory('SomeService', function ($window) {
    return {
        get: function(){
            return { firstname : "Joe" };
        }
    };
});

app.factory('Title', function ($window) {
    return {
        set: function(val){
            $window.document.title = val;
        }
    };
});

Ví dụ hoạt động ... http://jsfiddle.net/8m379/1/


5

Nếu bạn không có quyền kiểm soát yếu tố tiêu đề (như mẫu web asp.net) thì đây là một số thứ bạn có thể sử dụng

var app = angular.module("myApp")
    .config(function ($routeProvider) {
                $routeProvider.when('/', {
                                            title: 'My Page Title',
                                            controller: 'MyController',
                                            templateUrl: 'view/myView.html'
                                        })
                            .otherwise({ redirectTo: '/' });
    })
    .run(function ($rootScope) {
        $rootScope.$on("$routeChangeSuccess", function (event, currentRoute, previousRoute) {
            document.title = currentRoute.title;
        });
    });

4

Cách đơn giản và bẩn sử dụng $rootScope:

<html ng-app="project">
<head>
<title ng-bind="title">Placeholder title</title>

Trong bộ điều khiển của bạn, khi bạn có dữ liệu cần thiết để tạo tiêu đề, hãy làm:

$rootScope.title = 'Page X'

4

Không có câu trả lời nào trong số này có vẻ đủ trực quan, vì vậy tôi đã tạo ra một chỉ thị nhỏ để làm điều này. Cách này cho phép bạn khai báo tiêu đề trong trang, nơi người ta thường làm điều đó và cũng cho phép nó hoạt động.

angular.module('myModule').directive('pageTitle', function() {
    return {
        restrict: 'EA',
        link: function($scope, $element) {
            var el = $element[0];
            el.hidden = true; // So the text not actually visible on the page

            var text = function() {
                return el.innerHTML;
            };
            var setTitle = function(title) {
                document.title = title;
            };
            $scope.$watch(text, setTitle);
        }
    };
});

Tất nhiên bạn sẽ cần phải thay đổi tên mô-đun để khớp với tên của bạn.

Để sử dụng nó, chỉ cần ném cái này vào chế độ xem của bạn, giống như bạn làm với một <title>thẻ thông thường :

<page-title>{{titleText}}</page-title>

Bạn cũng có thể chỉ bao gồm văn bản đơn giản nếu bạn không cần nó bằng động:

<page-title>Subpage X</page-title>

Ngoài ra, bạn có thể sử dụng một thuộc tính để làm cho nó thân thiện hơn với IE:

<div page-title>Title: {{titleText}}</div>

Tất nhiên, bạn có thể đặt bất cứ văn bản nào bạn muốn vào thẻ, bao gồm cả mã Angular. Trong ví dụ này, nó sẽ tìm kiếm$scope.titleText bất kỳ bộ điều khiển nào mà thẻ tiêu đề tùy chỉnh hiện đang ở.

Chỉ cần đảm bảo rằng bạn không có nhiều thẻ tiêu đề trang trên trang của mình, nếu không chúng sẽ ghi đè lên nhau.

Ví dụ về Plunker tại đây http://plnkr.co/edit/nK63te7BSbCxLeZ2ADHV . Bạn sẽ phải tải xuống zip và chạy nó cục bộ để xem thay đổi tiêu đề.


Tôi đã đưa ra một cái gì đó tương tự. Cho đến nay, trực quan nhất để sử dụng và không yêu cầu đặt bộ điều khiển html. Trong chỉ thị của tôi, tôi cũng tiêm một pageTitlePrefixhằng số tùy chọn .
z0r

4

Giải pháp đơn giản cho angular-ui-router:

HTML:

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

Khối App.js> myApp.config

$stateProvider
    .state("home", {
        title: "My app title this will be binded in html title",
        url: "/home",
        templateUrl: "/home.html",
        controller: "homeCtrl"
    })

App.js> myApp.run

myApp.run(['$rootScope','$state', function($rootScope,$state) {
   $rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams) {
    $rootScope.title = $state.current.title;
    console.log($state);
   });
}]);

3

Đây là một cách khác nhau để thay đổi tiêu đề. Có thể không có khả năng mở rộng như một chức năng của nhà máy (có thể hiểu được các trang không giới hạn) nhưng tôi dễ hiểu hơn:

Trong index.html của tôi, tôi bắt đầu như thế này:

    <!DOCTYPE html>
      <html ng-app="app">
        <head>
          <title ng-bind-template="{{title}}">Generic Title That You'll Never See</title>

Sau đó, tôi đã thực hiện một phần gọi là "nav.html":

<div ng-init="$root.title = 'Welcome'">
    <ul class="unstyled">
        <li><a href="#/login" ng-click="$root.title = 'Login'">Login</a></li>
        <li><a href="#/home" ng-click="$root.title = 'Home'">Home</a></li>
        <li><a href="#/admin" ng-click="$root.title = 'Admin'">Admin</a></li>
        <li><a href="#/critters" ng-click="$root.title = 'Crispy'">Critters</a></li>
    </ul>
</div>

Sau đó, tôi đã quay lại "index.html" và thêm nav.html bằng cách sử dụng ng-include và ng-view cho các phần của tôi:

<body class="ng-cloak" ng-controller="MainCtrl">
    <div ng-include="'partials/nav.html'"></div>
    <div>
        <div ng-view></div>
    </div>

Chú ý rằng ng-cloak? Nó không liên quan gì đến câu trả lời này nhưng nó ẩn trang cho đến khi tải xong, một cú chạm đẹp :) Tìm hiểu cách thức ở đây: Các yếu tố Angularjs - ng-cloak / ng-show nhấp nháy

Đây là mô-đun cơ bản. Tôi đặt nó trong một tệp có tên "app.js":

(function () {
    'use strict';
    var app = angular.module("app", ["ngResource"]);

    app.config(function ($routeProvider) {
        // configure routes
        $routeProvider.when("/", {
            templateUrl: "partials/home.html",
            controller:"MainCtrl"
        })
            .when("/home", {
            templateUrl: "partials/home.html",
            controller:"MainCtrl"
        })
            .when("/login", {
            templateUrl:"partials/login.html",
            controller:"LoginCtrl"
        })
            .when("/admin", {
            templateUrl:"partials/admin.html",
            controller:"AdminCtrl"
        })
            .when("/critters", {
            templateUrl:"partials/critters.html",
            controller:"CritterCtrl"
        })
            .when("/critters/:id", {
            templateUrl:"partials/critter-detail.html",
            controller:"CritterDetailCtrl"
        })
            .otherwise({redirectTo:"/home"});
    });

}());

Nếu bạn nhìn về phía cuối mô-đun, bạn sẽ thấy rằng tôi có một trang chi tiết critter dựa trên: id. Đó là một phần được sử dụng từ trang Crispy Critters. [Corny, tôi biết - có thể đó là một trang web tôn vinh tất cả các loại cốm gà;) Dù sao, bạn có thể cập nhật tiêu đề khi người dùng nhấp vào bất kỳ liên kết nào, vì vậy trong trang Crispy Critters chính của tôi dẫn đến trang chi tiết critter, đó là nơi cập nhật $ root.title sẽ diễn ra, giống như bạn đã thấy trong nav.html ở trên:

<a href="#/critters/1" ng-click="$root.title = 'Critter 1'">Critter 1</a>
<a href="#/critters/2" ng-click="$root.title = 'Critter 2'">Critter 2</a>
<a href="#/critters/3" ng-click="$root.title = 'Critter 3'">Critter 3</a>

Xin lỗi rất nhiều gió nhưng tôi thích một bài viết cung cấp đủ chi tiết để có được nó và chạy. Lưu ý rằng trang ví dụ trong tài liệu AngularJS đã hết hạn và hiển thị phiên bản 0.9 của ng-bind-template. Bạn có thể thấy rằng nó không khác nhau nhiều.

Suy nghĩ lại: bạn biết điều này nhưng nó ở đây cho bất cứ ai khác; ở dưới cùng của index.html, người ta phải bao gồm app.js với mô-đun:

        <!-- APP -->
        <script type="text/javascript" src="js/app.js"></script>
    </body>
</html>

2
Ý kiến ​​của tôi, không sử dụng này. Bạn đang trộn dữ liệu (thông tin) trong chế độ xem (trình bày). Sau này, sẽ rất khó để tìm các nguồn tiêu đề nằm rải rác trên tất cả các liên kết HTML của bạn có thể có mặt ở nhiều nơi khác nhau trong chế độ xem ..
amit bakle

Vì tiêu đề chỉ được cập nhật khi thực sự nhấp vào một liên kết , nên điều này không đặt tiêu đề chính xác khi người dùng lần đầu tiên đặt chân lên một trang hoặc khi người dùng làm mới.
Đánh dấu Amery

3

Khi tôi phải giải quyết vấn đề này, tôi không thể đặt thẻ ng-apptrên trang html, vì vậy tôi đã giải quyết nó bằng một dịch vụ:

angular.module('myapp.common').factory('pageInfo', function ($document) {

    // Public API
    return {
        // Set page <title> tag. Both parameters are optional.
        setTitle: function (title, hideTextLogo) {
            var defaultTitle = "My App - and my app's cool tagline";
            var newTitle = (title ? title : defaultTitle) + (hideTextLogo ? '' : ' - My App')
            $document[0].title = newTitle;
        }
    };

});

2

Giải pháp dựa trên sự kiện tùy chỉnh lấy cảm hứng từ Michael Bromley

Tôi không thể làm cho nó hoạt động với $ scope, vì vậy tôi đã thử với rootScope, có thể hơi bẩn hơn một chút ... (đặc biệt là nếu bạn làm mới trên trang không đăng ký sự kiện)

Nhưng tôi thực sự thích ý tưởng về cách mọi thứ được kết nối lỏng lẻo.

Tôi đang sử dụng angularjs 1.6.9

index.run.js

angular
.module('myApp')
.run(runBlock);

function runBlock($rootScope, ...)
{
  $rootScope.$on('title-updated', function(event, newTitle) {
    $rootScope.pageTitle = 'MyApp | ' + newTitle;
  });
}

anyControll.controll.js

angular
.module('myApp')
.controller('MainController', MainController);

function MainController($rootScope, ...)
{
  //simple way :
  $rootScope.$emit('title-updated', 'my new title');

  // with data from rest call
  TroncQueteurResource.get({id:tronc_queteur_id}).$promise.then(function(tronc_queteur){
  vm.current.tronc_queteur = tronc_queteur;

  $rootScope.$emit('title-updated', moment().format('YYYY-MM-DD') + ' - Tronc '+vm.current.tronc_queteur.id+' - ' +
                                             vm.current.tronc_queteur.point_quete.name + ' - '+
                                             vm.current.tronc_queteur.queteur.first_name +' '+vm.current.tronc_queteur.queteur.last_name
  );
 });

 ....}

index.html

<!doctype html>
<html ng-app="myApp">
  <head>
    <meta charset="utf-8">
    <title ng-bind="pageTitle">My App</title>

Nó làm việc cho tôi :)



1

Trong khi những người khác có thể có các phương thức tốt hơn, tôi có thể sử dụng $ rootScope trong các bộ điều khiển của mình, vì mỗi chế độ xem / mẫu của tôi có một bộ điều khiển riêng biệt. Bạn sẽ cần phải tiêm $ rootScope trong mỗi bộ điều khiển. Trong khi điều này có thể không lý tưởng, nó hoạt động với tôi, vì vậy tôi nghĩ tôi nên vượt qua nó. Nếu bạn kiểm tra trang, nó sẽ thêm ng-ràng buộc vào thẻ tiêu đề.

Trình điều khiển ví dụ:

myapp.controller('loginPage', ['$scope', '$rootScope', function ($scope, $rootScope) {

// Dynamic Page Title and Description
$rootScope.pageTitle = 'Login to Vote';
$rootScope.pageDescription = 'This page requires you to login';
}]);

Ví dụ Index.html tiêu đề:

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<meta name="description" content="{{pageDescription}}">
<meta name="author" content="">
<link rel="shortcut icon" href="../../assets/ico/favicon.ico">
<base href="/">
<title>{{pageTitle}}</title>

Bạn cũng có thể đặt pageTitle và pageDes mô tả thành các giá trị động, chẳng hạn như trả về dữ liệu từ một cuộc gọi REST:

    $scope.article = restCallSingleArticle.get({ articleID: $routeParams.articleID }, function() {
    // Dynamic Page Title and Description
    $rootScope.pageTitle = $scope.article.articletitle;
    $rootScope.pageDescription = $scope.article.articledescription;
});

Một lần nữa, những người khác có thể có ý tưởng tốt hơn về cách tiếp cận điều này, nhưng vì tôi đang sử dụng kết xuất trước, nên nhu cầu của tôi đang được đáp ứng.


0

Cảm ơn tosh shimayama cho giải pháp của mình.
Tôi nghĩ rằng việc đưa dịch vụ vào thẳng là không sạch sẽ $scope, vì vậy đây là biến thể nhỏ của tôi về điều đó: http://plnkr.co/edit/QJbuZZnZEDOBcYrJXWWs

Bộ điều khiển (trong câu trả lời ban đầu có vẻ hơi ngu ngốc) tạo ra một đối tượng ActionBar và cái này được nhồi vào $ scope.
Đối tượng chịu trách nhiệm thực sự truy vấn dịch vụ. Nó cũng ẩn trong phạm vi $ cuộc gọi để đặt URL mẫu, thay vào đó có sẵn cho các bộ điều khiển khác để đặt URL.


0

Ông Hash đã có câu trả lời tốt nhất cho đến nay, nhưng giải pháp dưới đây khiến nó trở nên lý tưởng (đối với tôi) bằng cách thêm các lợi ích sau:

  • Không có đồng hồ, có thể làm chậm mọi thứ
  • Trên thực tế tự động hóa những gì tôi có thể đã làm trong bộ điều khiển, nhưng
  • Vẫn cho tôi quyền truy cập từ bộ điều khiển nếu tôi vẫn muốn.
  • Không tiêm thêm

Trong bộ định tuyến:

  .when '/proposals',
    title: 'Proposals',
    templateUrl: 'proposals/index.html'
    controller: 'ProposalListCtrl'
    resolve:
      pageTitle: [ '$rootScope', '$route', ($rootScope, $route) ->
        $rootScope.page.setTitle($route.current.params.filter + ' ' + $route.current.title)
      ]

Trong khối chạy:

.run(['$rootScope', ($rootScope) ->
  $rootScope.page =
    prefix: ''
    body: ' | ' + 'Online Group Consensus Tool'
    brand: ' | ' + 'Spokenvote'
    setTitle: (prefix, body) ->
      @prefix = if prefix then ' ' + prefix.charAt(0).toUpperCase() + prefix.substring(1) else @prifix
      @body = if body then ' | ' + body.charAt(0).toUpperCase() + body.substring(1) else @body
      @title = @prefix + @body + @brand
])

-4

Giải pháp tốt hơn và năng động hơn mà tôi đã tìm thấy là sử dụng $ watch để theo dõi các thay đổi của biến và sau đó cập nhật tiêu đề.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.