UI-Router를 사용하여 페이지 제목 설정


101

기본 제공 라우팅 대신 ui-router를 사용하도록 AngularJS 기반 앱을 마이그레이션하고 있습니다. 아래와 같이 구성했습니다.

.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 변수를 설정하는 코드를 반복해야합니다.


3
$ stateChangeSuccess 이벤트가 있습니다.
Jerrad

답변:


108

사용 $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


훌륭합니다. 이 couldnt는 어떤 쉽게 얻을
마 우드에게

3
이 예제는 또한 기록과 함께 제대로 작동하지 않습니다 (적어도 Chrome 37에서는). 여러 상태 사이를 이동 한 다음 기록을 보면 기록 항목의 제목이 이전 페이지의 값이됩니다. page1-> page2-> page3으로 이동하면 히스토리를 보면 page2의 URL이 page1의 제목과 일치합니다.
jkjustjoshing 2014 년

2
사실, 그것은 정확하지 않습니다. URL 해시가 변경되기 전에 페이지 제목이 변경되므로 브라우저는 새 제목이 이전 페이지 용이라고 생각합니다. 뒤로 버튼 기록은 한 페이지 떨어져 있습니다. element.text(title)$ timeout으로 전화를 래핑하는 것이 저에게 효과적이었습니다. 원본 게시물 편집.
jkjustjoshing 2014 년

3
제목이 일부 URL 매개 변수를 기반으로 동적이어야하는 경우 작동하지 않습니다.
Kushagra Gour 2014 년

10
@KushagraGour 제목이 $ stateParams를 기반으로 동적이어야하는 경우, 함수를 사용 resolve하여 생성 한 다음 $ stateChangeSuccess 이벤트 동안 다음을 사용하여 "resolved"값에 액세스 할 수 있습니다 $state.$current.locals.resolve.$$values.NAME_OF_RESOLVE_FUNCTION..
Claus Conrad

91

이미 여기에 대부분의 답변을 결합하여이를 수행하는 또 다른 방법이 있습니다. 이미 답변을 받았지만 ui-router를 사용하여 페이지 제목을 동적으로 변경하는 방법을 보여주고 싶었습니다.

ui-router 샘플 app을 살펴보면 각 .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>

이것이 이전의 답변보다 낫다고 말할 수는 없지만 이해하고 구현하기가 더 쉬웠습니다. 이것이 누군가를 돕기를 바랍니다!


3
허용되는 답변보다 선언적입니다. 나는 이것을 좋아한다!
Endy Tjahjono

3
확실하지 나는 ... 그냥 제목으로 $ rootScope에서 전체 $ 범위 객체를 좋아하면
헤수스 카레라

나는 확실히 $ 범위 객체가 JesúsCarrera @ 참조되는없는 곳이야
cwbutler

UPS는, 미안 해요는 $ 상태 개체 의미
헤수스 카레라

4
단지 확인 github.com/angular-ui/ui-router/wiki/Quick-Reference은 또한 설정을 권장 $state하고 $stateParams$rootScope내에서 run.
Mark Peterson

17

볼록 UI 라우터 타이틀 플러그인은 쉽게 페이지 제목 업데이트하게 정적 또는 동적 의 현재 상태에 기초하여 값. 브라우저 기록에서도 올바르게 작동합니다.


이것은 앞으로의 최선의 해결책 인 것 같습니다. 이 페이지의 다른 솔루션 중 일부를 사용하여 브라우저 기록과 몇 가지 불일치를 발견했습니다.

angular-ui-router-title이 최선의 해결책 인 것 같습니다. 무엇보다도 번거롭지 않습니다! 감사합니다 스테판.
Dário

아주 작은 소스 파일입니다.
Tyler Collier 2015 년

15

$stateChangeSuccess이제 UI-Router 1.x에서 더 이상 사용되지 않으며 기본적으로 비활성화됩니다. 이제 새 $transition서비스 를 사용해야합니다 .

$transition작동 방식 을 이해하면 해결책은 그리 어렵지 않습니다 . 모든 것을 이해하는 @troig의 도움 을 받았습니다 . 제목을 업데이트하기 위해 제가 생각 해낸 것입니다.

이것을 Angular 1.6 응용 프로그램에 넣으십시오. ECMAScript 6 구문을 사용하고 있습니다. 그렇지 않은 경우 예를 들어으로 변경 let해야 var합니다.

.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상태 자체 될 함수를 호출하는 데 사용하고, 하나의 인자는이 예와 같이, 상태 변수가 될 것이다 :

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

/bar/code/123페이지 제목으로 "바코드 123"을 표시 하는 URL 경로의 경우 . ECMAScript 6 구문을 사용하여 문자열 형식을 지정하고 params.code.

시간이있는 사람이 이와 같은 것을 지시문에 넣어 모든 사람이 사용할 수 있도록 게시하면 좋을 것입니다.


data사용자 지정 키에 개체를 사용 합니다. 인터페이스에 title존재하지 않습니다 StateDeclaration.
Gaui

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


1
이것을 각 주에 제목을 추가하는 것과 결합했습니다. 완벽하게 작동합니다.
WCByrne

5

나는 발견 이 방법은 정말 쉽습니다 :

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

다음과 같이 내 HTML에서 :

<h3>{{ $state.current.title }}</h3>

5

window.document.title을 업데이트하십시오.

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

이렇게하면 'ng-app'이 HTML 태그 위로 이동할 필요가 없으며 본문 또는 아래에 머물 수 있습니다.


1
이것이 최선의 답변이 아닌 이유는 무엇입니까? = /
rex

3

나는 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.'
    },
  })

2

실제로 첫 번째 답변 / 질문에 정말 가깝습니다. 제목을 데이터 개체로 추가합니다.

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

1

나는 Martin과 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; 
   });
});

템플릿 관련 항목이 없다면 새 개발자가 제목이 어떻게 변경되었는지 묻지 않고 어떻게 변경되었는지 어떻게 알 수 있을까요?
ton.yeung

$ window.document.title을 사용하면 $ timeout은 쓸모가 없습니다. :) 난 그냥 $ 시간 제한을 없애려면이 hackish을 다음있어하고 사이클을 소화 $
위스커

1

왜 안 되는가 :

$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}}">

잠재적으로 발견하기가 매우 어려울 수 없었던 이유 / 제목은 코드베이스를 상속 사람을 위해 변경하는 방법
ton.yeung

왜 알아 내기 어려울까요? 이 스니핑은 your-page-titile = "{{ 'pageTitle'| translate}}와 같은 지시문에서 트리거되어야합니다.이 지시문은 모든 페이지의 첫 번째 요소에 포함됩니다. 멋지고 선언적인 명확합니다.
Martin

오, 편집을 통해 이제 무슨 뜻인지 알겠습니다. 내가 뭘 의미하는 것은 ... 하나의 라이너가 잠재적으로 어디서나 등 $ rootscope, 지시어를 넣을 수 있다고했다
ton.yeung

0

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

이 지시문을 시도해 볼 수 있습니다.

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>

자바 스크립트 :

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

업데이트 된 UI-Router 1.0.0+ 버전의 경우 ( https://ui-router.github.io/guide/ng1/migrate-to-1_0 )

다음 코드를 참조하십시오

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>

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.