UI-Router kullanarak Sayfa başlığını ayarlayın


101

AngularJS tabanlı uygulamamı yerleşik yönlendirme yerine ui-yönlendiriciyi kullanacak şekilde geçiriyorum. Aşağıda gösterildiği gibi yapılandırdım

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

Sayfanın başlığını dinamik olarak ayarlamak için pageTitle değişkenini nasıl kullanabilirim? Yerleşik yönlendirmeyi kullanarak yapabilirim

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

ve sonra değişkeni aşağıda gösterildiği gibi HTML olarak bağlayın

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

UI yönlendiriciyi kullanarak bağlanabileceğim benzer bir olay var mı? 'OnEnter' ve 'onExit' fonksiyonlarının olduğunu fark ettim, ancak bunlar her duruma bağlı görünüyor ve her durum için $ rootScope değişkenini ayarlamak için kodu tekrarlamamı gerektirecek.


3
$ StateChangeSuccess olayı var.
Jerrad

Yanıtlar:


108

Kullanım $stateChangeSuccess .

Bir yönergeye koyabilirsiniz:

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

Ve:

<title update-title></title>

Demo: http://run.plnkr.co/8tqvzlCw62Tl7t4j/#/home

Kod: http://plnkr.co/edit/XO6RyBPURQFPodoFdYgX?p=preview

Hatta ile tarih doğru olduğu için ihtiyaç duyulan olmuştur, en azından ben kendimi test ettik zaman.$stateChangeSuccess$timeout


Düzenleme: 24 Kasım 2014 - Bildirici yaklaşım:

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

Ve:

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

Demo: http://run.plnkr.co/d4s3qBikieq8egX7/#/credits

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


Süper harika. Bu daha kolay olamazdı
Matthew Harwood

3
Bu örnek aynı zamanda geçmişle düzgün çalışmıyor (en azından Chrome 37'de). Çeşitli durumlar arasında gidip, ardından geçmişinize bakarsanız, geçmiş öğesinin başlığı önceki sayfanın değeri olacaktır. Sayfa1 -> sayfa2 -> sayfa3'e giderseniz, geçmişe bakarsanız, sayfa2'nin url'si sayfa1'in başlığıyla eşleşecektir.
jkjustjoshing

2
Aslında bu pek doğru değil. Sayfa başlığı, URL karması değişmeden önce değişir, bu nedenle tarayıcı yeni başlığın eski sayfa için olduğunu düşünür. Geri düğmesi geçmişi 1 sayfa kapalıdır. element.text(title)Aramayı $ zaman aşımına sarmak benim için çalıştı. Orijinal gönderiyi düzenleme.
jkjustjoshing

3
Başlığın bazı url parametrelerine göre dinamik olması gerekiyorsa bu işe yaramaz.
Kushagra Gour

10
Başlık ihtiyaçları $ stateParams göre dinamik olarak @KushagraGour varsa, bir işlev kullanabilirsiniz resolvebunu üretmek için, daha sonra $ stateChangeSuccess olay sırasında "çözüldü" değerini erişmek: $state.$current.locals.resolve.$$values.NAME_OF_RESOLVE_FUNCTION.
Claus Conrad

91

Buradaki yanıtların çoğunu birleştirerek bunu yapmanın başka bir yolu daha var. Bunun zaten yanıtlandığını biliyorum ama ui-router ile sayfa başlıklarını dinamik olarak nasıl değiştirdiğimi göstermek istedim.

Ui -router örnek uygulamasına bir göz atarsanız , $ state değişkenini $ rootScope'a eklemek için açısal .run bloğunu kullanırlar.

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

Bu tanımla, sayfa başlığınızı, tanımladığınız durumu kullanmak için yayınladığınız ancak değiştirdiklerinizle dinamik olarak kolayca güncelleyebilirsiniz:

Durumu aynı şekilde ayarlayın:

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

Ama html'yi biraz düzenleyin ...

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

Bunun önceki cevaplardan daha iyi olduğunu söyleyemem ... ama benim için anlamak ve uygulamak daha kolaydı. Umarım bu birine yardımcı olur!


3
Kabul edilen cevaptan daha açıklayıcı. Bunu severim!
Endy Tjahjono

3
$ RootScope'taki tüm $ kapsam nesnesini yalnızca sayfa başlığı için isteyip istemediğimden emin değilim ...
Jesús Carrera

$ Kapsam nesnesinin nerede başvurulduğundan emin değilim @ JesúsCarrera
cwbutler

Ups, üzgünüm $ durum nesnesi demek
Jesús Carrera

4
Sadece onaylamak için github.com/angular-ui/ui-router/wiki/Quick-Reference da ayarı önerir $stateve $stateParamsüzerinde $rootScopeiçinden run.
Mark Peterson

17

Açısal-ui-yönlendirici-başlık eklentisi kolay bir sayfa başlığı güncellemeyi kolaylaştırır statik veya dinamik geçerli durumuna göre değer. Tarayıcı geçmişiyle de doğru şekilde çalışır.


Bu ileriye dönük en iyi çözüm gibi görünüyor. Bu sayfadaki diğer çözümlerden bazılarını kullanırken tarayıcı geçmişinde birkaç tutarsızlık fark ettim.

angular-ui-router-title, en iyi çözüm gibi görünüyor. Hepsinden önemlisi sorunsuz! Teşekkürler Stepan.
Dário

Bu çok küçük bir kaynak dosyası.
Tyler Collier

15

$stateChangeSuccessartık UI-Router 1.x'te kullanımdan kaldırılmıştır ve varsayılan olarak devre dışı bırakılmıştır. Şimdi yeni $transitionhizmeti kullanmanız gerekecek .

Nasıl $transitionçalıştığını anladıktan sonra çözüm çok zor değildir . Her şeyi anlamak için @troig'den biraz yardım aldım . İşte başlığı güncellemek için bulduğum şey.

Bunu Angular 1.6 uygulamanıza koyun. ECMAScript 6 sözdizimini kullandığımı unutmayın; değilseniz, örneğin, olarak değiştirmeniz letgerekecektir 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;
        }
    });

Ardından title, durumunuza bir dize ekleyin :

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

Bu, başlıkta "Foo Page" kelimelerinin görünmesini sağlayacaktır. (Bir eyaletin başlığı yoksa sayfa başlığı güncellenmeyecektir. Durum bir durumu belirtmiyorsa, varsayılan bir başlık sağlamak için yukarıdaki kodu güncellemek basit bir şey olacaktır.)

Kod ayrıca için bir işlev kullanmanıza izin verir title. thisDevletin kendisi olacaktır işlevi çağırmak için kullanılan ve bir argüman bu örnekteki gibi devlet parametreleri, olacaktır:

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

/bar/code/123Sayfa başlığı olarak "Barkod 123" gösterilecek URL yolu için. Dizeyi biçimlendirmek ve ayıklamak için ECMAScript 6 sözdizimini kullandığımı unutmayın params.code.

Zamanı olan birinin böyle bir şeyi bir yönergeye koyması ve herkesin kullanması için yayınlaması güzel olurdu.


Kullanım dataözel tuşlar için nesne. arayüzde titlemevcut değil StateDeclaration.
Gaui

5

Uygulamanın herhangi bir yerinde kullanmak için $ state'i $ rootcope'a ekleniyor.

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
Bunu her duruma başlık ekleyerek birleştirdik. Mükemmel çalışıyor.
WCByrne

5

Bu yolu gerçekten çok kolay buldum :

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

ve sonra HTML’imde şöyle:

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

5

Window.document.title dosyasını güncellemeniz yeterlidir:

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

Bu şekilde 'ng-app'in HTML etiketine gitmesine gerek kalmaz ve gövde üzerinde veya daha aşağıda kalabilir.


1
Neden bu en iyi cevap değil? = /
rex

3

Sadece sayfa başlığını ayarlamak için değil aynı zamanda açıklamalar için de iyi çalışan ngMeta kullanıyorum . Her durum için belirli bir başlık / açıklama, bir başlık / açıklama belirtilmediğinde varsayılanlar ve ayrıca varsayılan başlık sonekleri (yani, '| SitemAdı') ve yazar değeri ayarlamanıza olanak tanır.

$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

Aslında ilk cevabınıza / sorunuza gerçekten çok yakınsınız. Başlığınızı bir veri nesnesi olarak ekleyin:

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

İndex.html dosyanızda verileri doğrudan sayfa başlığına bağlayın:

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

1

Sonunda Martin'in ve tasseKATT'ın cevaplarının bu kombinasyonunu buldum - basit ve şablonla ilgili herhangi bir şey olmadan:

$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; 
   });
});

şablonla ilgili herhangi bir şey yoksa, yeni bir geliştirici, başlığın nasıl değiştirildiğini sormadan nasıl değiştirildiğini nasıl bilebilir?
ton.yeung

$ window.document.title $ zaman aşımı kullanırsanız işe yaramaz. Sadece $ zaman aşımından ve $ sindirim döngüsünden kurtulmak için bu hileyi takip ediyorum :)
Whisher

1

Neden sadece:

$window.document.title = 'Title';

GÜNCELLEME: Tam Yönerge Kodu

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);

Sonra her sayfaya şu yönergeyi dahil edersiniz:

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

kod tabanını miras alan herkes için başlığın neden / nasıl değiştiğini bulmak potansiyel olarak çok zor olabilir
ton.yeung

Bunu öğrenmek neden zor? Bu, bir yönergeden tetiklenmelidir, örneğin your-page-titile = "{{'pageTitle' | translate}}. Bu yönerge, her sayfanın ilk öğesine dahil edilecektir. Güzel ve açıklayıcı.
Martin

Oh, düzenleme ile, şimdi ne demek istediğini anlıyorum. Demek istediğim, bir astarın potansiyel olarak herhangi bir yere konulabileceğiydi, $ rootcope, yönerge vb.
ton.yeung

0

ES6 kullanıyorsanız, bu gayet iyi çalışıyor :).

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

Belki bu yönergeyi deneyebilirsiniz.

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

İşte örnek:

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

Güncellenmiş UI-Router 1.0.0+ sürümleri için, ( https://ui-router.github.io/guide/ng1/migrate-to-1_0 )

Aşağıdaki koda bakın

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

İndex.html dosyanıza aşağıdakileri ekleyin:

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.