如何基于AngularJS局部视图动态更改标题?

How to dynamically change header based on AngularJS partial view?

提问人:Michael Low 提问时间:9/20/2012 最后编辑:tanguy_kMichael Low 更新时间:5/4/2018 访问量:273502

问:

我正在使用 ng-view 来包含 AngularJS 部分视图,我想根据包含的视图更新页面标题和 h1 标题标签。不过,这些超出了部分视图控制器的范围,因此我无法弄清楚如何将它们绑定到控制器中的数据集。

如果它是 ASP.NET MVC,您可以使用 @ViewBag 来执行此操作,但我不知道 AngularJS 中的等效项。我已经搜索了共享服务、活动等,但仍然无法让它工作。任何修改我的示例使其有效的方法将不胜感激。

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

我的 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"; }
javascript angularjs 模板 部分视图 angular-routing

评论

0赞 Kamuran Sönecek 4/7/2016
这个评论可能晚了,但我想补充一下。 cssfacts.com/simple-dynamic-meta-tags-in-angularjs 这对于设置动态元很有用。您只需更改$rootScope元变量即可。

答:

342赞 Tosh 9/20/2012 #1

您可以在级别定义控制器。<html>

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

您可以创建 service: 并从控制器进行修改。Page

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

从控制器注入并调用“Page.setTitle()”。Page

下面是具体的例子:http://plnkr.co/edit/0e7T6l

评论

11赞 superjos 3/7/2013
呃......我不确定在 AngularJS 架构中将服务直接放入$scope是否被认为是好的。也许最好放入 $scope Controller 函数,然后让此函数查询服务。
11赞 Arthur Frankel 5/18/2013
这个例子太棒了。不过我有一个后续,在初始加载时,您可以在标题中看到 {{ Page.title() }} 文本(很快)。我不认为你可以使用 ng-cloak,因为它不在体内。有什么建议可以避免这种情况吗?
52赞 Pius Uzamere 8/14/2013
@ArthurFrankel 只需使用 ng-bind(例如 ng-bind=“Page.title()”)
2赞 Dmitri Algazin 5/14/2014
或者我们可以在 title 标签中指定控制器,不需要在 html 标头上使用全局控制器: <title ng-controller=“titleCtrl”>{{ Page.title() }}</title>
6赞 DDA 7/19/2014
我个人更喜欢设置标题,而不是创建额外的控制器。$rootScope
3赞 noogrub 9/22/2012 #2

这是进行标题更改的不同方法。也许不像工厂功能那样可扩展(可以想象它可以处理无限的页面),但它对我来说更容易理解:

在我的索引.html中,我是这样开始的:

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

然后我做了一个部分叫做“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>

然后我回到“index.html”并使用ng-include和ng-view为我的部分添加了nav.html:

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

注意到ng斗篷了吗?它与这个答案没有任何关系,但它隐藏了页面,直到它完成加载,这是一个很好的触摸:)在这里了解如何操作:Angularjs - ng-cloak/ng-show 元素闪烁

这是基本模块。我把它放在一个名为“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"});
    });

}());

如果你看一下模块的末尾,你会看到我有一个基于 :id 的 critter-detail 页面。这是 Crispy Critters 页面中使用的部分。[老生常谈,我知道——也许这是一个庆祝各种鸡块的网站;)无论如何,当用户点击任何链接时,你可以更新标题,所以在我的 Crispy Critters 主页中,它指向 critter-detail 页面,这就是 $root.title 更新的地方,就像你在上面的导航中看到的那样.html:

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

对不起,风太大了,但我更喜欢一个提供足够细节来启动和运行它的帖子。请注意,AngularJS 文档中的示例页面已过时,并显示 ng-bind-template 的 0.9 版本。你可以看到它并没有太大的不同。

事后思考:你知道这一点,但它是为其他人准备的;在索引 .html 的底部,必须将 app.js 包含在模块中:

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

评论

2赞 amit bakle 7/22/2014
我的意见,不要用这个。您正在视图(演示文稿)中混合数据(信息)。稍后,将很难找到分散在 HTML 链接中的标题源,这些源可能存在于视图中的各个位置。
0赞 Mark Amery 1/28/2015
由于标题仅在实际单击链接时才会更新,因此当用户首次登陆页面或用户刷新时,这不会正确设置标题。
633赞 jkoreska 11/16/2012 #3

如果您使用路由,我刚刚发现了一种设置页面标题的好方法:

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

编辑:使用属性而不是卷曲,这样它们就不会在加载时显示ng-bind{{}}

评论

11赞 Eric Drechsel 5/21/2013
是的,但您的示例没有显示如何更改由 $scope 变量参数化的$routeChangeSuccess上的标题,而@tosh使用 Page 服务的示例就是这样做的。所以你可以设置,但不能.title = "Blog"title = '{{"Blog post " + post.title}}'
10赞 Eldelshell 7/18/2013
@felix您也可以访问标题current.title
8赞 david.sansay 9/13/2013
$rootScope.title = current.$route.title;没有 doble $$
7赞 Tyler Forsythe 3/19/2014
我刚刚将我的 Angular 版本升级了几个版本(1.0.5 到 1.2.7),这让我在代码中崩溃了。我在旧代码中使用并且它正在工作。随着升级,需要双倍的$在途中。current.$routecurrent.$$route
6赞 jbltx 12/8/2014
在 answser 中,当可以看到 .有什么方法可以用这种方法获得价值吗?我试过了,但没有用......也许使用 ?'/Product/:id':idtitle: function(params){return params.id;}resolve
197赞 broc.seib 1/28/2013 #4

请注意,您也可以直接使用 javascript 设置标题,即

$window.document.title = someTitleYouCreated;

这没有数据绑定,但当放入标签有问题时就足够了。(例如,使用 JSP 模板,其中恰好在一个地方定义,但您有多个应用程序。ng-app<html><head>

评论

2赞 Lukus 7/31/2013
很好的直接方法,让你想起显而易见的事情。我简单地将其包装在我的“ui”服务中作为 setTitle() 函数,注入了$window依赖项,并且由于我的服务在我所有的控制器中,现在可以在任何控制器中调用 ui.setTitle('example title')。
5赞 Maarten 8/5/2013
对我来说,这是让它在 Internet Explorer 上运行的唯一方法,但其他方法在其他浏览器上也有效
4赞 rob 9/18/2013
正如 Maarten 所提到的,这是唯一适用于 ie7 和 ie8 的方法
8赞 broc.seib 12/23/2014
使用普通的“window”是可以的——它直接作用在DOM上。 “$window”是一个有棱角的东西,你必须注入它才能使用它。无论哪种方式都可以。
1赞 sidonaldson 4/8/2015
$window只是一个包装器,因此您可以集成和操作它以进行自动化测试。如果你只是想设置一些东西,请直接:)
0赞 superjos 3/7/2013 #5

感谢 tosh shimayama 的解决方案。
我认为将服务直接放入 并不那么干净,所以这是我对此的细微变化: http://plnkr.co/edit/QJbuZZnZEDOBcYrJXWWs
$scope

控制器(在最初的答案中,在我看来有点太愚蠢了)创建了一个 ActionBar 对象,这个对象被塞进了$scope。
该对象负责实际查询服务。它还对设置模板 URL 的调用$scope隐藏,而其他控制器可以使用模板 URL 来设置 URL。

120赞 Andy Hitchman 5/31/2013 #6

在元素上声明可为 和 提供根作用域。ng-apphtmlheadbody

因此,在控制器中注入并设置标头属性:$rootScope

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

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

并在您的页面中:

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

评论

8赞 Nicolas Janel 6/1/2014
我的意见的最佳答案。在这种情况下,在 ng-app 级别拥有一个控制器,如接受的答案中所述是没有用的。
0赞 special0ne 11/11/2014
被接受的答案增加了不必要的复杂性和风险。此版本使它像设置变量一样简单。
3赞 Michael J. Calkins 12/6/2014
如果你对使用$rootScope死心塌地,我至少会把它提取到一个服务中,这样你的控制器中就没有$rootScope了。
3赞 remarsh 12/11/2014
我想使用这个解决方案,但我很好奇使用它有什么好处document.title = "App";
0赞 Rober 2/27/2015
您的解决方案是否适用于此方案?stackoverflow.com/questions/28760904/......
5赞 JeremyWeir 7/20/2013 #7

对于没有包含该标签的 ngApp 的场景,只需向需要设置窗口标题的控制器注入服务即可。title

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

工作示例...http://jsfiddle.net/8m379/1/

32赞 Mr Hash 7/27/2013 #8

这是一个适合我的改编解决方案,它不需要将$rootScope注入控制器以设置特定于资源的页面标题。

在主模板中:

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

在路由配置中:

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

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

在运行块中:

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

最后在控制器中:

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

评论

1赞 Kristo Aun 2/9/2015
ProductController ($scope.page.setTitle) 中设置的标题被 $rootScope.$on('$routeChangeSuccess') 覆盖。在这方面,在 $rootScope.$on('$routeChangeStart' 中设置默认标题更安全。
0赞 mikhail-t 2/12/2015
@mr-hash:这是我建议的小调整,非常适合具有许多路由但没有标题的现有 angular 项目。如果路由上未定义任何标题,它将根据控制器的名称生成标题:$rootScope.page.setTitle(current.$$route.title || current.$$route.controller.replace('Ctrl', ''));
1赞 Henrik Stenbæk 8/6/2015
请记住像这样清理输出:this.title = title.replace('<', '&lt;').replace('>', '&gt;').replace(' & ', ' &amp; ') + ' | Site Name';
0赞 Andy 1/31/2016
我得到了未定义的错误,所以我将最后一位更改为: $rootScope.page.title = current.$$route ?current.$$route.title + ' |站点名称' : '站点名称';
5赞 Ashish 8/7/2013 #9

如果您无法控制标题元素(例如 asp.net Web 表单),您可以使用以下一些东西

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赞 user1338062 11/18/2013 #10

简单而肮脏的使用方式:$rootScope

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

在控制器中,当您拥有创建游戏所需的数据时,请执行以下操作:

$rootScope.title = 'Page X'
43赞 Martin Atkins 12/8/2013 #11

模块 angularjs-viewhead 显示了一种仅使用自定义指令在每个视图的基础上设置标题的机制。

它可以应用于其内容已为视图标题的现有视图元素:

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

...或者它可以用作独立元素,在这种情况下,该元素在呈现的文档中将不可见,并且仅用于设置视图标题:

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

此指令的内容在根作用域中作为 提供,因此它可以像任何其他变量一样用于 title 元素:viewTitle

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

它也可以用于任何其他可以“看到”根示波器的地方。例如:

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

此解决方案允许通过用于控制演示文稿其余部分的相同机制来设置标题:AngularJS 模板。这避免了使用这种表示逻辑使控制器混乱的需要。控制器需要提供将用于通知标题的任何数据,但模板最终决定如何呈现它,并且可以使用表达式插值和筛选器像往常一样绑定到范围数据。

(免责声明:我是本模块的作者,但我在这里引用它只是希望它能帮助其他人解决这个问题。

评论

4赞 Martin Wawrusch 8/17/2014
简直不敢相信这个解决方案没有得到更多的支持。其他大多数都是非常糟糕的设计选择。
0赞 Nate Barbettini 12/13/2014
同意,这应该是最好的解决方案。我更喜欢这比在页面级别声明一个控制器来设置标题要好得多。仅供参考:将其与 Angular v1.3.2 和 angular-route-segment v1.3.3 一起使用,它就像一个魅力。
0赞 jkoreska 4/10/2015
我赞同这个解决方案;)
3赞 Martin Atkins 6/14/2015
我在我的博客上写了更多关于angularjs-viewhead和另一个相关的想法:apparently.me.uk/angularjs-view-specific-sidebars
0赞 anre 1/29/2016
如果在顶层视图和子级视图中重用相同的视图,仍然可以将 view-title 与 ng-if 一起使用,例如: <h4 ng-if=“$state.includes('some-state')” view-title>Details for {{...}}</h4> <h4 ng-if=“!$state.includes('some-state')”>{{...}} 的详细信息</小时4>
16赞 Deminetix 3/18/2014 #12

如果您事先知道标题,Jkoreska 的解决方案是完美的,但您可能需要根据从资源等获得的数据来设置标题。

我的解决方案需要单一服务。由于 rootScope 是所有 DOM 元素的基础,因此我们不需要像有人提到的那样在 html 元素上放置控制器

页面.js

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

index.翡翠

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

所有需要更改标题的控制器

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

评论

0赞 Dmitri Algazin 5/14/2014
小问题,当您刷新页面时,在选项卡名称中您会看到“{{ title }}”,而在页面呈现后,您只会看到“Some Title”。工厂的解决方案没有这种行为
5赞 Faradox 8/7/2015
请改用{{title}}ng-bind='title'
1赞 Seth 9/24/2015
同意@Faradox...using 可防止在标题实际计算之前显示预插值语法。+100ng-bind
7赞 Michael Bromley 3/28/2014 #13

基于事件的自定义解决方案

这是其他人尚未提及的另一种方法(在撰写本文时)。

您可以像这样使用自定义事件:

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

这种方法的优点是不需要编写额外的服务,然后注入到每个需要设置标题的控制器中,并且也不(ab)使用 .它还允许您设置动态标题(如代码示例中所示),这在路由器的配置对象上使用自定义数据属性是不可能的(至少据我所知)。$rootScope

11赞 Alex Soroka 7/7/2014 #14

一种允许动态设置标题或元描述的干净方式。例如,我使用 ui-router,但您可以以相同的方式使用 ngRoute。

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>
...
4赞 MikeyB 7/22/2014 #15

这些答案似乎都不够直观,所以我创建了一个小指令来做到这一点。这种方式允许您在页面中声明标题,通常这样做,并且还允许它是动态的。

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

当然,您需要更改模块名称以匹配您的模块名称。

要使用它,只需将其放在您的视图中,就像您对常规标签所做的那样:<title>

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

如果您不需要纯文本,也可以只包含纯文本,通过动态:

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

或者,您可以使用属性,使其更适合 IE:

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

当然,你可以在标签中放置任何你想要的文本,包括 Angular 代码。在此示例中,它将在 custom-title 标记当前所在的任何控制器中查找。$scope.titleText

只要确保你的页面上没有多个页面标题标签,否则它们会互相干扰。

这里的 Plunker 示例 http://plnkr.co/edit/nK63te7BSbCxLeZ2ADHV。您必须下载 zip 并在本地运行它才能看到标题更改。

评论

0赞 z0r 6/25/2015
我想出了类似的东西。到目前为止,使用起来最直观,并且不需要打开控制器。在我的指令中,我还注入了一个可选常量。htmlpageTitlePrefix
8赞 Nathan Kot 7/26/2014 #16

或者,如果您使用的是 ui-router

索引:.html

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

路由

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

评论

2赞 11/8/2014
我无法让它工作..我已经根据我的状态更新了 URL 和内容,并且没有收到任何错误或警告,但我似乎无法通过 .你用什么版本来做这件事?ui-router$state.current.[...]ui-router
0赞 11/8/2014
我对答案的“运行时配置”编辑解决了我在上面的评论中提到的问题。:)不过,如果有更好的方法可以做到这一点,我对想法持开放态度。
0赞 GraehamF 1/14/2016
这对我不起作用,并且在 API 文档中找不到“标题” - 这仍然受支持吗?
0赞 Kim Miller 8/24/2014 #17

到目前为止,Hash 先生得到了最好的答案,但下面的解决方案通过添加以下好处使其成为理想的(对我来说):

  • 不添加手表,这会减慢速度
  • 实际上自动化了我可能在控制器中完成的工作,但是
  • 如果我仍然需要它,仍然允许我从控制器访问它。
  • 无需额外注射

在路由器中:

  .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)
      ]

在 run 块中:

.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赞 geolyth 12/31/2014 #18

我发现的更好的动态解决方案是使用 $watch 来跟踪变量更改,然后更新标题。

1赞 Kode 3/8/2015 #19

虽然其他人可能有更好的方法,但我能够在我的控制器中使用$rootScope,因为我的每个视图/模板都有一个不同的控制器。您需要在每个控制器中注入$rootScope。虽然这可能不理想,但它对我来说是有效的,所以我认为我应该把它传递下去。如果检查页面,它会将 ng-binding 添加到标题标签中。

示例控制器:

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

示例索引 .html 标头:

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

还可以将 pageTitle 和 pageDescription 设置为动态值,例如从 REST 调用返回数据:

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

同样,其他人可能对如何处理这个问题有更好的想法,但由于我使用的是预渲染,我的需求得到了满足。

3赞 Tom Söderlund 6/11/2015 #20

当我必须解决这个问题时,我无法将 放在页面的标签上,所以我用一个服务解决了它:ng-apphtml

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

});
4赞 the_mishra 6/9/2017 #21

angular-ui-router 的简单解决方案:

HTML格式 :

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

应用.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);
   });
}]);
2赞 Thomas 5/4/2018 #22

Michael Bromley 启发的基于自定义事件的解决方案

我无法让它与$scope一起工作,所以我尝试使用 rootScope,也许有点脏......(特别是当您在未注册事件的页面上刷新时)

但我真的很喜欢事物如何松散耦合的想法。

我正在使用 angularjs 1.6.9

索引.run,.js

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

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

任何控制器.控制器,.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
  );
 });

 ....}

索引:.html

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

它对我有用:)