Как динамически изменить заголовок на основе частичного представления AngularJS?


411

Я использую 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"; }

Этот комментарий может быть поздно, но я хочу добавить. cssfacts.com/simple-dynamic-meta-tags-in-angularjs Это может быть полезно для установки динамических метасов. Вы просто измените мета-переменную $ rootScope.
— Камуран Сёнечек

Ответы:


342

Вы можете определить контроллер на <html>уровне.

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

Вы создаете сервис: 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


11
хм ... я не уверен, что размещение сервиса прямо в $ scope считается хорошим в архитектуре AngularJS. Возможно, было бы лучше поместить в $ scope функцию Controller, а затем позволить этой функции запрашивать службу.
— Superjos

11
Этот пример был потрясающим. У меня есть одно продолжение, хотя при начальной загрузке вы можете увидеть текст {{Page.title ()}} в заголовке (очень быстро). Я не думаю, что вы можете использовать нг-плащ, так как его нет в теле. Любые предложения, чтобы избежать этого?
— Артур Франкель

52
@ArthurFrankel Просто используйте ng-bind (например, ng-bind = "Page.title ()")
— Pius Uzamere

2
или мы можем указать контроллер в теге title, нет необходимости в глобальном контроллере в заголовке html: <title ng-controller = "titleCtrl"> {{Page.title ()}} </ title>
— Дмитрий Алгазин

6
Я лично предпочитаю устанавливать заголовок $rootScopeвместо создания дополнительного контроллера.
— DDA

634

Я только что нашел хороший способ установить заголовок страницы, если вы используете маршрутизацию:

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
верно, но ваш пример не показывает, как изменить заголовок в $ routeChangeSuccess, параметризованный переменными $ scope, как это делает пример @ tosh с использованием службы Page. Таким образом, вы можете установить, title = "Blog"но не title = '{{"Blog post " + post.title}}'.
— Эрик Дрехсель

10
@felix вы можете получить доступ к названию, как current.titleтакже
— Eldelshell

8
$ rootScope.title = current. $ route.title; без дубликата $$
— david.sansay

7
Я только что обновил свою версию Angular на несколько версий (1.0.5 до 1.2.7), и это сломало меня в моем коде. Я использовал current.$routeв старом коде, и он работал. При обновлении необходим двойной $ на маршруте. current.$$route
— Тайлер Форсайт

6
В ответчике когда сможете увидеть '/Product/:id'. Есть ли способ получить :idзначение с помощью этого метода? Я пытался, title: function(params){return params.id;}но не работает ... Может быть, с помощью resolve?
— mickaelb91

190

Обратите внимание, что вы также можете установить заголовок непосредственно с помощью JavaScript, т.е.

$window.document.title = someTitleYouCreated;

Это не имеет привязки данных, но достаточно , если положить ng-appв <html>теге является проблематичным. (Например, при использовании шаблонов JSP, где <head>определено ровно в одном месте, у вас есть несколько приложений.)


5
Это был единственный способ заставить его работать в Internet Explorer, другие методы работали в других браузерах
— Maarten

4
Как упоминал Мартен, это единственный подход, который работает в ie7 и ie8
— rob

33
Удивительно, как люди не могут отступить и увидеть, как легко это можно сделать без
— границ

7
Невероятно. Это было намного проще, чем все махинации, которые упоминали другие. Спасибо!
— Леонард Тео

8
Использовать простое «окно» хорошо - это напрямую влияет на DOM. '$ window' - угловатая вещь, и вы должны ввести ее, чтобы использовать. В любом случае будет работать.
— broc.seib 22.12.14

119

Объявление ng-appна htmlэлементе обеспечивает корневой простор для как headи body.

Поэтому в вашем контроллере введите $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
лучший ответ на мой взгляд. Иметь контроллер на уровне ng-app, как описано в принятом ответе, в этом случае бесполезно.
— Николас Джанель

1
Мне нравится, насколько легким является это решение, и оно избегает использования $$ properties
— tedwards947

Принятый ответ добавляет ненужные осложнения и риски. Эта версия делает это так же просто, как установка переменной.
— special0ne

3
Если вы не можете использовать $ rootScope, я бы по крайней мере извлек это в службу, чтобы у вас не было $ rootScope в вашем контроллере.
— Майкл Дж. Калкинс

3
Я хочу использовать это решение, но мне любопытно, каковы преимущества его использования document.title = "App";
— Restrsh

43

Модуль 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. Это позволяет избежать необходимости загромождать контроллеры этой логикой представления. Контроллер должен предоставлять любые данные, которые будут использоваться для информирования заголовка, но шаблон окончательно определяет, как его представлять, и может использовать интерполяцию выражений и фильтры для привязки к данным области как обычно.

(Отказ от ответственности: я являюсь автором этого модуля, но я ссылаюсь на него здесь только в надежде, что он поможет кому-то еще решить эту проблему.)


4
Не могу поверить, что за это решение больше не голосовали. Большинство других действительно плохих дизайнерских решений.
— Мартин Вавруш,

Согласитесь, это должно быть лучшим решением. Мне это нравится намного лучше, чем объявление контроллера на уровне страницы для установки заголовка. К вашему сведению: используйте это с Angular v1.3.2 и angular-route-сегмента v1.3.3, и это работает как шарм.
— Нейт Барбеттини

Я одобряю это решение;)
— jkoreska

3
Я написал немного больше об angularjs-viewhead и другой связанной с этим идее здесь, в моем блоге: очевидно.me.uk/
— Мартин Аткинс

Если повторно использовать один и тот же вид на верхнем уровне и на уровне подуровня, можно по-прежнему использовать view-title с ng-if, например: <h4 ng-if = "$ state.include ('some-state')" view-title> Подробности для {{...}} </ h4> <h4 ng-if = "! $ state.includes ('some-state')">> Детали для {{...}} </ h4 >
— НАРЭ

32

Вот адаптированное решение, которое работает для меня, которое не требует внедрения $ 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
Набор заголовков в ProductController ($ scope.page.setTitle) переопределяется $ rootScope. $ On ('$ routeChangeSuccess'. Установка заголовка по умолчанию в $ rootScope. $ On ('$ routeChangeStart' безопаснее в этом отношении.
— Кристо Аун

@ mr-hash: я предлагаю небольшую настройку, которая идеально подходит для существующих угловых проектов с большим количеством маршрутов, но без заголовков. Он будет генерировать заголовок из имени контроллера, если заголовок не определен на маршруте:$rootScope.page.setTitle(current.$$route.title || current.$$route.controller.replace('Ctrl', ''));
— mikhail-t

1
Не забудьте санировать вывод следующим образом:this.title = title.replace('<', '&lt;').replace('>', '&gt;').replace(' & ', ' &amp; ') + ' | Site Name';
— Хенрик Стенбек

Я получил неопределенную ошибку, поэтому я изменил последний бит на: $ rootScope.page.title = current. $$ route? текущий. $$ route.title + '| Имя сайта »:« Имя сайта »;
— Энди

15

Решение jkoreska идеально подходит, если вы знаете заголовки заранее, но вам может потребоваться установить заголовок на основе данных, которые вы получаете от ресурса и т. д.

Мое решение требует одного сервиса. Поскольку rootScope является основой всех элементов DOM, нам не нужно помещать контроллер в элемент HTML, как кто-то упоминал

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

Все контроллеры, которые должны изменить заголовок

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

небольшая проблема: когда вы обновляете страницу, в имени вкладки вы видите «{{title}}», а после рендеринга страницы вы видите только «Some Title». решение с завода не имеет такого поведения
— Дмитрий Алгазин

5
вместо этого {{title}}используйтеng-bind='title'
— Фарадокс

1
Согласитесь с @Faradox ... using ng-bindпредотвращает отображение предварительно интерполированного синтаксиса до того, как заголовок действительно оценивается. +100
— Сет

11

Чистый способ, который позволяет динамически устанавливать заголовок или мета-описание. В примере я использую 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>
...

8

В качестве альтернативы, если вы используете ui-router :

index.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
Я не могу заставить это работать ... Я ui-routerобновляю URL и контент на основе своего состояния, и я не получаю ошибок или предупреждений, но я не могу получить доступ к какой-либо части объекта конфигурации состояния через $state.current.[...]. Какую версию ui-routerвы использовали для этого?

Моя «Runtime Config», редактирующая ответ, решает проблему, о которой я упоминал в своем комментарии выше. :) Я открыт для идей, если есть лучший способ сделать это все же.

это не работает для меня, и 'title' не найден в документации API - это все еще поддерживается?
— GraehamF

7

Индивидуальное решение на основе событий

Вот еще один подход, который не был упомянут другими здесь (на момент написания статьи).

Вы можете использовать пользовательские события, например, так:

// 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. Это также позволяет вам установить динамический заголовок (как в примере кода), что невозможно при использовании пользовательских атрибутов данных в объекте конфигурации маршрутизатора (насколько я знаю, по крайней мере).


5

Для сценариев, в которых у вас нет 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/


5

Если вы не можете контролировать элемент title (например, веб-форму asp.net), вот что вы можете использовать

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

Простой и грязный способ использования $rootScope:

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

В ваших контроллерах, когда у вас есть данные, необходимые для создания заголовка, выполните:

$rootScope.title = 'Page X'

4

Ни один из этих ответов не казался достаточно интуитивным, поэтому я создал небольшую директиву для этого. Этот способ позволяет вам объявить заголовок на странице, где обычно это делается, и позволяет ему быть динамичным.

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>

Вы можете поместить любой текст в тег, который вы хотите, включая угловой код. В этом примере он будет искать $scope.titleTextв любом контроллере, в котором находится тег пользовательского заголовка.

Просто убедитесь, что на вашей странице нет нескольких тегов заголовка страницы, иначе они будут слипаться.

Пример плунжера здесь http://plnkr.co/edit/nK63te7BSbCxLeZ2ADHV . Вам нужно скачать zip и запустить его локально, чтобы увидеть изменение названия.


Я придумал что-то подобное. Безусловно, наиболее интуитивно понятен в использовании и не требует установки контроллера html. В моей директиве я также добавляю необязательную pageTitlePrefixконстанту.
— z0r

4

Упрощенное решение для angular-ui-router:

HTML:

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

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

Вот другой способ сделать изменения названия. Возможно, не так масштабируемо, как фабричная функция (которая могла бы обрабатывать неограниченное количество страниц), но мне было легче понять:

В моем index.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» и добавил nav.html, используя ng-include и ng-view для моих партиалов:

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

Заметьте, что нг-плащ? Он не имеет никакого отношения к этому ответу, но он скрывает страницу до тех пор, пока она не загрузится, приятное прикосновение :) Узнайте, как здесь: 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. Это часть, которая используется на странице Crispy Critters. [Корни, я знаю - может быть, это сайт, который празднует все виды куриных самородков;) В любом случае, вы можете обновить заголовок, когда пользователь нажимает на любую ссылку, поэтому на моей главной странице Crispy Critters, которая ведет на страницу с подробностями о существе, вот куда пойдет обновление $ root.title, как вы видели в nav.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. Вы можете видеть, что это не так сильно отличается.

Запоздалая мысль: вы знаете это, но это здесь для всех остальных; в нижней части index.html необходимо включить app.js с модулем:

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

2
Мое мнение, не используйте это. Вы смешиваете данные (информацию) в представлениях (презентации). Позже будет очень трудно найти источники заголовков, разбросанные по всем вашим HTML-ссылкам, которые могут присутствовать в различных местах представления ...
— amit bakle

Поскольку заголовок обновляется только после фактического нажатия на ссылку , заголовок не устанавливается правильно, когда пользователь впервые попадает на страницу или когда пользователь обновляется.
— Марк Эмери

3

Когда мне пришлось решить эту проблему, я не мог разместить тег ng-appна странице html, поэтому я решил это с помощью службы:

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

Специальное решение на основе событий, вдохновленное Майклом Бромли

Я не смог заставить его работать с $ scope, поэтому я попытался с rootScope, возможно, немного более грязным ... (особенно если вы делаете обновление на странице, которая не регистрирует событие)

Но мне действительно нравится идея о том, как вещи слабо связаны.

Я использую 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;
  });
}

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

Это работает для меня :)



1

В то время как другие могут иметь лучшие методы, я смог использовать $ rootScope в своих контроллерах, так как каждый из моих представлений / шаблонов имеет отдельный контроллер. Вам нужно будет вставить $ rootScope в каждый контроллер. Хотя это может и не быть идеальным, оно работает для меня, поэтому я подумал, что должен это передать. Если вы просматриваете страницу, она добавляет привязку ng к тегу title.

Пример контроллера:

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

Пример заголовка Index.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;
});

Снова, у других могут быть лучшие идеи относительно того, как приблизиться к этому, но так как я использую предварительный рендеринг, мои потребности удовлетворяются.


0

Спасибо Тошу Симаяма за его решение.
Я думал, что не очень-то чисто поставить сервис прямо в $scope, так что вот мое небольшое изменение: http://plnkr.co/edit/QJbuZZnZEDOBcYrJXWWs

Контроллер (который в первоначальном ответе показался мне слишком тупым) создает объект ActionBar, и этот объект помещается в $ scope.
Объект отвечает за фактический запрос сервиса. Он также скрывает от $ scope вызов для установки URL-адреса шаблона, который вместо этого доступен другим контроллерам для установки URL-адреса.


0

У Мистера Хэша был лучший ответ, но приведенное ниже решение делает его идеальным (для меня), добавляя следующие преимущества:

  • Не добавляет часов, которые могут замедлить ход событий
  • На самом деле автоматизирует то, что я мог бы сделать в контроллере, пока
  • По-прежнему дает мне доступ с контроллера, если я все еще хочу это.
  • Никаких дополнительных инъекций

В роутере:

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

-4

Лучшее и динамичное решение, которое я нашел, - это использовать $ watch для отслеживания изменений переменных, а затем обновить заголовок.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.