0

I am trying to make a Single Page App using Angular and I want to dynamically change the page titles based on views. I tried doing it using directives as shown in the following code:

<!-- index.html !-->

<html ng-app="MyApp">
<head>
    <page-title></page-title>         <!-- ....................LINE 1   !-->
    <script type="text/javascript"
        src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.js">
    </script>
    <script type="text/javascript"
        src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular-route.js">
    </script>
    <script type="text/javascript"
        src="/js/index.js">
    </script>
</head>

<body>
        <nav-bar></nav-bar>
        <div ng-view></div>
        ...

Below is my directive code:

app.directive('pageTitle', function() {
   return {
      controller: 'titleController',
      template: '<title>{{ page.title }}</title>'  //.............LINE 2
   }
});

Titles are changing as expected. Everything is working perfectly except the fact that whatever code that should be inside the <head> tag, now moves inside the body including the title, style and script tags. This is bad for SEO. I searched for the problem and found some alternative solutions to do the same on this link but not the exact solution and explanation to this anomaly. I even tried changing LINE 1 and LINE 2 as follows:

<title><page-title></page-title></title>    << LINE 1

template: '{{ page.title }}'                << LINE 2

And this gets it even more unexpected. It doesn't change the title at all and instead prints out <page-title></page-title> straight on every page's title as if no directive is defined for <page-title> tag. I want some explanation on both of these anomalies in Angular. :(

Community
  • 1
  • 1
UtkarshPramodGupta
  • 7,486
  • 7
  • 30
  • 54
  • How do you define your `$scope.page.title`? Could you add in the controller code? –  Dec 07 '16 at 22:25

1 Answers1

0

Not sure how you define your page title but you could do something along these lines and define page title in the stateProvider

app.config(['$stateProvider', '$urlRouterProvider',
  function($stateProvider, $urlRouterProvider) {

    $urlRouterProvider.otherwise('/home');

    $stateProvider
      .state('home', {
        url: '/home',
        templateUrl: 'home.html',
        data: {
          pageTitle: 'Home'
        }
      })
      .state('about', {
        url: '/about',
        templateUrl: 'about.html',
        data: {
          pageTitle: 'About'
        }
      })
      .state('credits', {
        url: '/credits',
        templateUrl: 'credits.html',
        data: {
          pageTitle: 'Credits'
        }
      });
  }
]);

As for your directive

app.directive('pageTitle', ['$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);
      }
    };
  }
]);

Then your page title tags <title page-title></title>

Setting element.text with your given text will sort it out as your just defining a new tag with template.