我使用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"; }
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(['$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
])
对于没有包含标题标签的ngApp的场景,只需向需要设置窗口标题的控制器注入服务。
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/
这些答案似乎都不够直观,所以我创建了一个小指令来做这件事。这种方式允许您在页面中声明标题,而通常情况下是这样做的,并允许它是动态的。
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代码。在本例中,它将查找$scope。无论自定义标题标签当前在哪个控制器中。
只要确保你的页面上没有多个页面标题标签,否则它们会互相攻击。
这里的Plunker例子http://plnkr.co/edit/nK63te7BSbCxLeZ2ADHV。您必须下载压缩文件并在本地运行,才能看到标题的变化。
你可以在<html>级别定义controller。
<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并调用'Page. settitle()'。
下面是一个具体的例子:http://plnkr.co/edit/0e7T6l
模块angularjs-viewhead展示了一种机制,它只使用自定义指令在每个视图的基础上设置标题。
它可以应用于一个已经存在的视图元素,其内容已经是视图标题:
<h2 view-title>About This Site</h2>
...或者它可以作为一个独立的元素使用,在这种情况下,元素将在呈现的文档中不可见,只用于设置视图标题:
<view-title>About This Site</view-title>
这个指令的内容在根作用域中作为viewTitle可用,所以它可以像其他变量一样用于title元素:
<title ng-bind-template="{{viewTitle}} - My Site">My Site</title>
它还可以用于任何其他可以“看到”根作用域的位置。例如:
<h1>{{viewTitle}}</h1>
这个解决方案允许通过与控制演示的其他部分相同的机制来设置标题:AngularJS模板。这避免了用这种表示逻辑使控制器混乱的需要。控制器需要提供用于通知标题的任何数据,但模板最终决定如何表示它,并且可以像往常一样使用表达式插值和过滤器绑定范围数据。
(免责声明:我是这个模块的作者,但我在这里引用它只是希望它能帮助其他人解决这个问题。)
这是一个适合我的解决方案,它不需要注入$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);
}