web-dev-qa-db-ja.com

UI-Routerを使用してページタイトルを設定する

AngularJSベースのアプリを移行して、組み込みのルーティングの代わりにui-routerを使用しています。以下に示すように構成しています

.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/home');
$stateProvider
    .state('home', {
        url: '/home',
        templateUrl : 'views/home.html',
        data : { pageTitle: 'Home' }

    })
    .state('about', {
        url: '/about',
        templateUrl : 'views/about.html',
        data : { pageTitle: 'About' }
    })
     });

PageTitle変数を使用してページのタイトルを動的に設定するにはどうすればよいですか?組み込みのルーティングを使用して、私はできる

$rootScope.$on("$routeChangeSuccess", function(currentRoute, previousRoute){
    $rootScope.pageTitle = $route.current.data.pageTitle;
  });

次に、次のようにHTMLで変数をバインドします

<title ng-bind="$root.pageTitle"></title>

Ui-routerを使用してフックできる同様のイベントはありますか? 「onEnter」関数と「onExit」関数があることに気付きましたが、それらは各状態に関連付けられているようで、各状態に$ rootScope変数を設定するコードを繰り返す必要があります。

100
user1625066

$stateChangeSuccessを使用します。

ディレクティブに入れることができます:

app.directive('updateTitle', ['$rootScope', '$timeout',
  function($rootScope, $timeout) {
    return {
      link: function(scope, element) {

        var listener = function(event, toState) {

          var title = 'Default Title';
          if (toState.data && toState.data.pageTitle) title = toState.data.pageTitle;

          $timeout(function() {
            element.text(title);
          }, 0, false);
        };

        $rootScope.$on('$stateChangeSuccess', listener);
      }
    };
  }
]);

そして:

<title update-title></title>

デモ:http://run.plnkr.co/8tqvzlCw62Tl7t4j/#/home

コード:http://plnkr.co/edit/XO6RyBPURQFPodoFdYgX?p=preview

$stateChangeSuccessであっても、少なくとも自分自身をテストしたときには、履歴を修正するために$timeoutが必要でした。


編集:2014年11月24日-宣言的アプローチ:

app.directive('title', ['$rootScope', '$timeout',
  function($rootScope, $timeout) {
    return {
      link: function() {

        var listener = function(event, toState) {

          $timeout(function() {
            $rootScope.title = (toState.data && toState.data.pageTitle) 
            ? toState.data.pageTitle 
            : 'Default title';
          });
        };

        $rootScope.$on('$stateChangeSuccess', listener);
      }
    };
  }
]);

そして:

<title>{{title}}</title>

デモ:http://run.plnkr.co/d4s3qBikieq8egX7/#/credits

コード:http://plnkr.co/edit/NpzQsxYGofswWQUBGthR?p=preview

107
tasseKATT

ここですでにほとんどの答えを組み合わせることで、これを行う別の方法があります。これは既に回答済みですが、ui-routerを使用してページタイトルを動的に変更する方法を示したかったのです。

Ui-router サンプルアプリ を見ると、angular 。run ブロックを使用して$ state変数を$ rootScopeに追加しています。

// It's very handy to add references to $state and $stateParams to the $rootScope
// so that you can access them from any scope within your applications.
// For example, <li ng-class="{ active: $state.includes('contacts.list') }"> 
// will set the <li> to active whenever 'contacts.list' or one of its 
// decendents is active.

.run([ '$rootScope', '$state', '$stateParams',
function ($rootScope, $state, $stateParams) {
  $rootScope.$state = $state;
  $rootScope.$stateParams = $stateParams;
}])

これを定義すると、投稿したが定義済みの状態を使用するように変更したものでページタイトルを簡単に動的に更新できます。

同じ方法で状態を設定します。

.state('home', {
    url: '/home',
    templateUrl : 'views/home.html',
    data : { pageTitle: 'Home' }
})

しかし、HTMLを少し編集してください...

<title ng-bind="$state.current.data.pageTitle"></title>

これは以前の答えよりも優れているとは言えませんが、理解して実装するのは簡単でした。これが誰かを助けることを願っています!

91
cwbutler

angular-ui-router-title プラグインを使用すると、ページタイトルをstaticまたはdynamic現在の状態に基づく値。ブラウザの履歴でも正しく機能します。

17
Stepan Riha

$stateChangeSuccessI-Router 1.xで非推奨 になり、デフォルトで無効になりました。新しい$transitionサービスを使用する必要があります。

$transitionの仕組みを理解すれば、解決策はそれほど難しくありません。すべてを理解するために、@-troigから help を入手しました。これが、タイトルを更新するために思いついたものです。

これをAngular 1.6アプリケーションに入れます。 ECMAScript 6構文を使用していることに注意してください。そうでない場合は、たとえばletvarに変更するには

.run(function($transitions, $window) {
    $transitions.onSuccess({}, (transition) => {
        let title = transition.to().title;
        if (title) {
            if (title instanceof Function) {
                title = title.call(transition.to(), transition.params());
            }
            $window.document.title = title;
        }
    });

次に、状態にtitle文字列を追加するだけです。

$stateProvider.state({
    name: "foo",
    url: "/foo",
    template: "<foo-widget layout='row'/>",
    title: "Foo Page""
});

これにより、タイトルに「Foo Page」という単語が表示されます。 (州にタイトルがない場合、ページのタイトルは更新されません。州がタイトルを示さない場合、デフォルトのタイトルを提供するために上記のコードを更新するのは簡単です。)

このコードでは、titleの関数を使用することもできます。関数の呼び出しに使用されるthisは状態そのものであり、次の例のように、1つの引数は状態パラメーターになります。

$stateProvider.state({
    name: "bar",
    url: "/bar/{code}",
    template: "<bar-widget code='{{code}}' layout='row'/>",
    title: function(params) {
        return `Bar Code ${params.code}`;
    }
});

URLパス/bar/code/123の場合、ページタイトルとして「Bar Code 123」が表示されます。 ECMAScript 6構文を使用して文字列をフォーマットし、params.codeを抽出していることに注意してください。

時間のある人がこのようなものをディレクティブに入れて、誰でも使用できるように公開してくれたらいいですね。

13
Garret Wilson

私は この方法 本当に簡単だと見つけました:

  .state('app.staff.client', {
    url: '/client/mine',
    title: 'My Clients'})

そして、このような私のHTMLで:

<h3>{{ $state.current.title }}</h3>
5
Mike Rouse

アプリ内のどこでも使用できるように$ stateを$ rootscopeにアタッチします。

app.run(['$rootScope', '$state', '$stateParams',
    function ($rootScope,   $state,   $stateParams) {

        // It's very handy to add references to $state and $stateParams to the $rootScope
        // so that you can access them from any scope within your applications.For example,
        // <li ng-class="{ active: $state.includes('contacts.list') }"> will set the <li>
        // to active whenever 'contacts.list' or one of its decendents is active.
        $rootScope.$state = $state;
        $rootScope.$stateParams = $stateParams;
    }
  ]
)
<title ng-bind="$state.current.name + ' - ui-router'">about - ui-router</title>
5
simbu

Window.document.titleを更新するだけです:

.state('login', {
   url: '/login',
   templateUrl: "/Login",
   controller: "loginCtrl",
   onEnter: function($window){$window.document.title = "App Login"; }
})

そうすれば、「ng-app」はHTMLタグまで移動する必要がなく、本文以下に留まることができます。

3
getsetbro

ngMeta を使用しています。これは、ページタイトルの設定だけでなく説明にも適しています。各状態の特定のタイトル/説明、タイトル/説明が指定されていない場合のデフォルト、デフォルトのタイトルサフィックス(つまり、 '| MySiteName')および作成者の値を設定できます。

$stateProvider
  .state('home', {
    url: '/',
    templateUrl: 'views/home.html',
    controller: 'HomeController',
    meta: {
      'title': 'Home',
      'titleSuffix': ' | MySiteName',
      'description': 'This is my home page description lorem ipsum.'
    },
  })
3
drichar

実際には、最初の回答/質問に本当に近づいています。タイトルをデータオブジェクトとして追加します。

.state('home', {
    url: '/home',
    templateUrl : 'views/home.html',
    data : { pageTitle: 'Home' }
})

Index.htmlで、データをページタイトルに直接バインドします。

<title data-ng-bind="$state.current.data.pageTitle + ' - Optional text'">Failsafe text</title>
2
Tristan

私はマーティンの答えとtasseKATTの答えのこの組み合わせになりました-シンプルで、テンプレート関連のものなし:

$rootScope.$on("$stateChangeSuccess", function (event, toState) {
   $timeout(function () { // Needed to ensure the title is changed *after* the url so that history entries are correct.
     $window.document.title = toState.name; 
   });
});
1
Rob

なぜだけではありません:

$window.document.title = 'Title';

更新:完全なディレクティブコード

var DIRECTIVE = 'yourPageTitle';

yourPageTitle.$inject = ['$window'];
function yourPageTitle($window: ng.IWindowService): ng.IDirective {

    return {
        link: (scope, element, attrs) => {

            attrs.$observe(DIRECTIVE, (value: string) => {

                $window.document.title = value;
            });
        }
    }
}

directive(DIRECTIVE, yourPageTitle);

次に、すべてのページに次のディレクティブを含めるだけです。

<section
    your-page-title="{{'somePage' | translate}}">
1
Martin

たぶん、このディレクティブを試すことができます。

https://github.com/afeiship/angular-dynamic-title

以下に例を示します。

html:

<title dynamic-title>Title</title>

<a href="javascript:;" ui-sref="state1">State1 page</a>
<a href="javascript:;" ui-sref="state2">State2 page</a>

javascript:

var TestModule = angular.module('TestApp', ['ui.router','nx.widget'])
    .config(function ($stateProvider, $urlRouterProvider) {
      //
      // For any unmatched url, redirect to /state1
      $urlRouterProvider.otherwise("/state1");
      //
      // Now set up the states
      $stateProvider
        .state('state1', {
          url: "/state1",
          templateUrl: "partials/state1.html",
          data:{
            pageTitle:'State1 page title11111'
          }
        })
        .state('state2', {
          url: "/state2",
          templateUrl: "partials/state2.html",data:{
            pageTitle:'State2 page title222222'
          }
        });
    })
    .controller('MainCtrl', function ($scope) {
      console.log('initial ctrl!');
    });
0
Fei Zheng

ES6を使用している場合、これは問題なく機能します:)。

class PageTitle {
    constructor($compile, $timeout) {
        this.restrict = 'A';
        this._$compile = $compile;
        this.$timeout = $timeout;
    }

    compile(element) {
        return this.link.bind(this);
    }

    link(scope, element, attrs, controller) {
        let defaultTitle = attrs.pageTitle ? attrs.pageTitle : "My Awesome Sauce Site";
        let listener = function(event, toState) {
            let title = defaultTitle;
            if (toState.data && toState.data.title) title = toState.data.title + ' | ' + title;
            $('html head title').text(title);
        };
        scope.$on('$stateChangeStart', listener);
    }
}

export function directiveFactory($compile) {
    return new PageTitle($compile);
}

directiveFactory.injections = ['$compile', '$timeout'];

export default PageTitle;
0
TGarrett

更新されたUI-Router 1.0.0+バージョンの場合、( https://ui-router.github.io/guide/ng1/migrate-to-1_

次のコードを参照してください

app.directive('pageTitle', [
    '$rootScope',
    '$timeout',
    '$transitions',
    function($rootScope, $timeout,$transitions) {
        return {
            restrict: 'A',
            link: function() {
                var listener = function($transitions) {
                    var default_title = "DEFAULT_TITLE";
                    $timeout(function() {
                                $rootScope.page_title = ($transitions.$to().data && $transitions.$to().data.pageTitle)
                            ? default_title + ' - ' + $transitions.$to().data.pageTitle : default_title;
                        
                        
                    });
                };
                $transitions.onSuccess({ }, listener);
            }
        }
    }
])

以下をindex.htmlに追加します。

<title page-title ng-bind="page_title"></title>
0
Palsri