Як динамічно змінювати заголовок на основі часткового перегляду 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.
Kamuran Sönecek

Відповіді:


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
умм ... я не впевнений, що розміщення послуги прямо в області $ вважається приємним в архітектурі AngularJS. Можливо, було б краще поставити в $ range функцію Controller, а потім дозволити цій функції запитувати службу.
superjos

11
Цей приклад був приголомшливим. У мене є один наступний процес, але при початковому завантаженні ви можете побачити текст {{Page.title ()}} у заголовку (дуже швидко). Я не думаю, що ти можеш використовувати ng-плащ, оскільки його немає в організмі. Будь-які пропозиції уникнути цього?
Артур Франкель

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

2
або ми можемо вказати контролер у заголовку тегу, немає необхідності у глобальному контролері в заголовку 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, параметризованому змінними $ range, що робить приклад @ tosh за допомогою послуги Page. Отже, ви можете встановити, title = "Blog"але ні title = '{{"Blog post " + post.title}}'.
Ерік Дрексель

10
@felix ви можете отримати доступ до заголовка, як current.titleтакож
Eldelshell

8
$ rootScope.title = поточний. $ route.title; без доблей $$
david.sansay

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

6
У answser коли може побачити '/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 для мене, хоча інші методи працювали і на інших браузерах
Маартен,

4
Як згадував Маартен, це єдиний підхід, який працює в ie7 і ie8
грабі

33
Дивовижно, як люди не можуть відступити і побачити, як легко цю справу можна зробити без областей і фабрик
redben

7
Неймовірно. Це було набагато простіше, ніж усі шенагігани, про які згадували інші. Дякую!
Леонард Тео

8
Використовувати звичайне "вікно" добре - це безпосередньо діє на DOM. '$ window' - це кутова річ, і вам потрібно вставити її, щоб використовувати її. Будь-який спосіб буде працювати.
broc.seib

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-додатків, як описано у прийнятій відповіді, в цьому випадку марно.
Ніколя Джанель

1
Мені подобається, наскільки легке це рішення, і він уникає використання $$ властивостей
tedwards947

Прийнята відповідь додає зайвих ускладнень та ризиків. Ця версія робить його таким же простим, як і встановлення змінної.
special0ne

3
Якщо ви готові використовувати $ rootScope, я принаймні витяг би це в сервіс, щоб у вашому контролері не було $ rootScope.
Майкл Дж. Калкінс

3
Я хочу використовувати це рішення, але мені цікаво, чим закінчуються переваги його використання document.title = "App";
ремарш

43

Модуль angularjs-viewhead показує механізм встановлення заголовка за оглядом за допомогою лише спеціальної директиви.

Він може бути застосований до існуючого елемента перегляду, вміст якого вже є заголовком перегляду:

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

... або він може бути використаний як окремий елемент, в цьому випадку елемент буде невидимим у наданому документі і буде використовуватися лише для встановлення заголовка перегляду:

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

Вміст цієї директиви надається в кореневій області як viewTitle, тому він може використовуватися в заголовковому елементі так само, як і будь-яка інша змінна:

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

Його також можна використовувати в будь-якому іншому місці, яке може "побачити" кореневу область. Наприклад:

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

Це рішення дозволяє встановлювати заголовок через той самий механізм, який використовується для управління рештою презентації: Шаблони AngularJS. Це дозволяє уникнути необхідності захаращувати контролери з цією логікою презентації. Контролеру необхідно надати будь-які дані, які будуть використані для інформування заголовка, але шаблон визначає остаточне визначення того, як його представити, і може використовувати інтерполяцію виразів та фільтри, щоб прив’язати до даних обсяг як звичайні.

(Відмова: Я є автором цього модуля, але я посилаюся на нього тут лише в надії, що він допоможе комусь іншому вирішити цю проблему.)


4
Не можу повірити, що це рішення не було схвалено більше. Більшість інших - це дуже поганий вибір дизайну.
Мартін Вавруш

Погоджено, це має бути найкращим рішенням. Мені це подобається набагато краще, ніж оголошення контролера на рівні сторінки для встановлення заголовка. FYI: використання цього з кутовим v1.3.2 та кутовим маршрутом v1.3.3, і це працює як шарм.
Нейт Барбеттіні

Я схвалюю це рішення;)
jkoreska

3
Я написав трохи більше про angularjs-viewhead та іншу пов’язану ідею тут у своєму блозі: очевидно.me.uk/
Мартін Аткінс

Якщо повторно використовувати один і той самий вигляд на верхньому та на підрівневому режимі, все одно можна використовувати заголовок представлення з ng-if, наприклад: <h4 ng-if = "$ state.includes ('some-state')" view-title> Деталі для {{...}} </h4> <h4 ng-if = "! $ state.includes ('some-state')"> Деталі для {{...}} </ h4 >
anre

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 ($ range.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}}", а після надання сторінки ви бачите лише "Деякий заголовок". рішення з фабрикою такої поведінки не має
Дмитро Алгазин

5
натомість {{title}}використовуйтеng-bind='title'
Faradox

1
Погодьтеся з використанням @Faradox ... використання ng-bindзапобігає відображенню попередньо інтерпольованого синтаксису до того, як заголовок фактично оцінить. +100
Сет

11

Чистий спосіб, що дозволяє динамічно встановлювати назву або метаопис. У прикладі я використовую ui-роутер, але ви можете використовувати 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-роутер :

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ви використовували для цього?

Моя редакція "Налаштування виконання" на відповідь вирішує проблему, про яку я згадував у своєму коментарі вище. :) Я відкритий до ідей, якщо є кращий спосіб зробити це.

це не працює для мене, і "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

Якщо ви не маєте контролю над елементом заголовка (наприклад, веб-формою 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в тому чи іншому контролері, де знаходиться тег спеціального заголовку.

Просто переконайтеся, що на вашій сторінці немає декількох тегів заголовка сторінки, інакше вони будуть розгублюватися.

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


Я придумав щось подібне. На сьогоднішній день найінтуїтивніший у використанні і не потребує введення контролера html. У своїй директиві я також вводять необов'язкові pageTitlePrefixконстанти.
z0r

4

Спрощене рішення для кутового ui-роутера:

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 застаріла і показує 0,9 версії ng-bind-шаблону. Ви можете бачити, що це не так вже й інакше.

Задумливість: ви знаєте це, але це тут для будь-кого іншого; У нижній частині 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

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

Мені не вдалося змусити його працювати з $ range, тому я спробував за допомогою 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-прив’язку до заголовкового тегу.

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

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

Контролер (що в оригінальній відповіді здавалося мені трохи німим) створює об'єкт ActionBar, і цей вкладений у $ range.
Об'єкт відповідає за фактичний запит на послугу. Він також приховує від $ діапазону виклик для встановлення 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.