使用UI-Router设置页面标题

101 angularjs angular-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' }
    })
     });
Run Code Online (Sandbox Code Playgroud)

如何使用pageTitle变量动态设置页面标题?使用内置路由,我可以做到

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

然后在HTML中绑定变量,如下所示

<title ng-bind="$root.pageTitle"></title>
Run Code Online (Sandbox Code Playgroud)

是否有类似的事件,我可以使用ui-router挂钩?我注意到有'onEnter'和'onExit'函数,但它们似乎与每个状态绑定,并且需要我重复代码为每个状态设置$ rootScope变量.

tas*_*ATT 107

使用$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);
      }
    };
  }
]);
Run Code Online (Sandbox Code Playgroud)

和:

<title update-title></title>
Run Code Online (Sandbox Code Playgroud)

演示: 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);
      }
    };
  }
]);
Run Code Online (Sandbox Code Playgroud)

和:

<title>{{title}}</title>
Run Code Online (Sandbox Code Playgroud)

演示: http ://run.plnkr.co/d4s3qBikieq8egX7/#/credits

代码: http ://plnkr.co/edit/NpzQsxYGofswWQUBGthR?p = preview

  • @KushagraGour如果标题需要基于$ stateParams是动态的,你可以使用`resolve`中的函数来生成它,然后在$ stateChangeSuccess事件期间使用:`$ state.$ current.locals访问"已解析"值. $$ .resolve.values.NAME_OF_RESOLVE_FUNCTION`. (10认同)
  • 此示例也无法正常使用历史记录(至少在Chrome 37中).如果您在各种状态之间切换,那么查看您的历史记录,历史记录项的标题将是上一页的值.如果你去page1 - > page2 - > page3,那么看看历史,page2的url将与page1的标题相匹配. (3认同)
  • 如果标题需要基于某些URL参数动态,则这将不起作用. (3认同)
  • 实际上,这并不是很准确.页面标题在URL哈希更改之前更改,因此浏览器认为新标题是针对旧页面.然后,后退按钮历史记录将关闭1页.在$ timeout中包含`element.text(title)`调用对我有用.编辑原始帖子. (2认同)
  • http://stackoverflow.com/questions/9083594/call-settimeout-without-delay (2认同)

cwb*_*ler 91

通过在这里结合大部分答案,还有另一种方法.我知道这已经回答了,但我想展示一下用ui-router动态更改页面标题的方式.

如果你看看ui-router 示例应用程序,他们使用角度.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;
}])
Run Code Online (Sandbox Code Playgroud)

通过此定义,您可以轻松地使用已发布的内容动态更新页面标题,但已修改为使用已定义的状态:

以相同的方式设置状态:

.state('home', {
    url: '/home',
    templateUrl : 'views/home.html',
    data : { pageTitle: 'Home' }
})
Run Code Online (Sandbox Code Playgroud)

但是编辑一下html ...

<title ng-bind="$state.current.data.pageTitle"></title>
Run Code Online (Sandbox Code Playgroud)

我不能说这比之前的答案更好......但我更容易理解和实施.希望这有助于某人!

  • 唯一的问题是历史.它以某种方式显示上一页的页面名称.. (7认同)
  • 只是为了确认https://github.com/angular-ui/ui-router/wiki/Quick-Reference还建议在`run`中的`$ rootScope`上设置`$ state`和`$ stateParams`. (4认同)
  • 比接受的答案更具说服力.我喜欢这个! (3认同)
  • 不确定我是否希望$ rootScope中的整个$ scope对象仅用于页面标题... (3认同)

小智 17

角的UI路由器标题插件可以很容易地更新页面标题为静态动态的基础上,当前状态值.它也适用于浏览器历史记录.


Gar*_*son 14

$stateChangeSuccess现在在UI-Router 1.x中弃用,默认情况下已禁用.您现在需要使用新$transition服务.

一旦了解了$transition工作方式,解决方案就不会太困难.我从@troig 那里得到了一些帮助来理解这一切.这是我提出的更新标题的内容.

把它放在你的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;
        }
    });
Run Code Online (Sandbox Code Playgroud)

然后只需title在您的州添加一个字符串:

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

这将使标题中出现"Foo Page"字样.(如果一个州没有标题,页面标题将不会更新.如果一个州没有表明一个,那么更新上面的代码以提供默认标题将是一件简单的事.)

该代码还允许您使用函数title.的this用来调用该函数将是国家本身,以及所述一个参数将是国家的参数,如下面的例子:

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

对于/bar/code/123将显示"条形码123"作为页面标题的URL路径.请注意,我正在使用ECMAScript 6语法格式化字符串并提取params.code.

如果有时间的人会把这样的东西放到指令中并发布给大家使用,那就太好了.


小智 5

将$ 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;
    }
  ]
)
Run Code Online (Sandbox Code Playgroud)
<title ng-bind="$state.current.name + ' - ui-router'">about - ui-router</title>
Run Code Online (Sandbox Code Playgroud)


Mik*_*use 5

我觉得很简单:

  .state('app.staff.client', {
    url: '/client/mine',
    title: 'My Clients'})
Run Code Online (Sandbox Code Playgroud)

然后在我的HTML中像这样:

<h3>{{ $state.current.title }}</h3>
Run Code Online (Sandbox Code Playgroud)


get*_*bro 5

只需更新 window.document.title:

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

这样 'ng-app' 不需要向上移动到 HTML 标签,并且可以停留在正文或下方。