Amb
Amb

Reputation: 3353

How can I update meta tags in AngularJS?

I am developing an application using AngularJS. I want to update meta tags on route change.
How can I update meta tags in AngularJS which can be shown in "view source" on the page?

here is a HTML code -

  <!DOCTYPE html>
    <html ng-app="app">
        <head>
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <meta name="fragment" content="!" />
            <meta name="title" content="Test App">
            <meta name="description" content="Test App">
            <meta name="keywords" content="Test,App">

            <link rel="stylesheet" href="css/jquery-ui-1.10.2.custom.min.css" />
            <link rel="stylesheet" href="css/extra.css" />
            <script src="js/libs/jquery-1.8.3.min.js"></script>
            <script src="js/libs/jquery-ui-1.10.2.custom.min.js"></script>
            <script src="js/libs/angular.min.js"></script>
            <script src="js/controller.js"></script>
            <script src="js/routes.js"></script>
        </head>
        <body>
            <div ng-controller="mainCtrl" class="main-container" loading>
                <div class="container-holder">
                    <div class="container">
                        <div ng-include src='"elements/header.html"'></div>
                        <div ng-view class="clearfix"></div>
                    </div>
                </div>

                <div ng-controller="userCtrl" id="test">
                    <div class="container" class="login-container">
                        <div id="login-logo">
                            <img src="images/logo-300.png" alt="" class="login-img"/>
                            <br />
                            <div ng-view></div>
                        </div>
                    </div>
                </div>
        </body>
    </html>

Upvotes: 40

Views: 45509

Answers (5)

Robo Rick
Robo Rick

Reputation: 789

I solved this very issue about 2 days ago, by creating a service, and using $window, plus some classic javascript.

In your html mark-up create whatever metatags you need... (feel free to leave them blank for now, or you can set them to a default value.)

<head> 
    <meta name="title"/>
    <meta name="description"/>
</head>

Then we'll need to create a service like so.

angular.module('app').service('MetadataService', ['$window', function($window){
 var self = this;
 self.setMetaTags = function (tagData){
   $window.document.getElementsByName('title')[0].content = tagData.title;
   $window.document.getElementsByName('description')[0].content = tagData.description;
 }; 
}]);

Now we'll need to use the "self.setMetaTags" service from within the controller (upon initialization)... you'll simply call the function anywhere on the controller.

angular.module('app').controller('TestController', ['MetadataService',function(MetadataService){

   MetadataService.setMetaTags({
       title: 'this',
       description: 'works'
    });

}]);

Upvotes: 9

Engineer_Andrew
Engineer_Andrew

Reputation: 604

I tweaked the answer found How to dynamically change header based on AngularJS partial view? to make this work on my site. You establish the meta content in the route config and then bind a function to the $routeChangeSuccess event to put the configured value into the $rootScope. As long as your meta tag is bound to the $rootScope value, everything will work out as planned.

angularApp.run(['$rootScope', function ($rootScope) {
    $rootScope.$on('$routeChangeSuccess', function (event, current, previous) {
        $rootScope.title = current.$$route.title;
        $rootScope.description = current.$$route.description;
        $rootScope.keywords = current.$$route.keywords;
    });
 }]);

angularApp.config(function ($routeProvider, $locationProvider) {
    $routeProvider
        .when('/About', {
            templateUrl: 'Features/About/About.html',
            title: 'Here\'s the Title',
            description: 'A Nice Description',
            keywords: 'Some, Keywords, Go, Here'
        });

    // use the HTML5 History API
    $locationProvider.html5Mode(true);
    $locationProvider.hashPrefix('!');
});

<head>
    <meta charset="utf-8" />
    <meta name="keywords" content="{{keywords}}"/>
    <meta name="description" content="{{description}}">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="fragment" content="!" />

    <title ng-bind="title">A Placeholder Title</title>
    <link rel="icon" href="/Images/Logo.ico">
    <base href="/" />
    @Styles.Render("~/Content/css")
</head>

Upvotes: 1

Jeff Whelpley
Jeff Whelpley

Reputation: 579

When you do 'view source' in most browsers, you see the document that was originally sent from the server before any JavaScript manipulation of the DOM. AngularJS apps typically do a lot of DOM manipulation but it never actually changes the original document. When you do something like right click -> inspect element in FireFox or Chrome (with dev tools) you will see the rendered DOM that includes all the JavaScript updates.

So, to answer your question there is no way to update the description meta tag with JavaScript such that the changes will be reflected in 'view source'. However, you can update the meta description tag so that any browser plugins (ex. bookmark apps, etc.) will see the updated description. To do that you would do something like this:

var metaDesc = angular.element($rootElement.find('meta[name=description]')[0]);
metaDesc.attr('content', description);

Upvotes: 1

kuceram
kuceram

Reputation: 3885

If you use angular-ui-router, you can use ui-router-metatags.

Upvotes: 8

Vijayabaskaran M
Vijayabaskaran M

Reputation: 613

<html ng-app="app">
    <title ng-bind="metaservice.metaTitle()">Test</title>
    <meta name="description" content="{{ metaservice.metaDescription() }}" />
    <meta name="keywords" content="{{ metaservice.metaKeywords() }}" />


<script>
    var app = angular.module('app',[]);
    app.service('MetaService', function() {
       var title = 'Web App';
       var metaDescription = '';
       var metaKeywords = '';
       return {
          set: function(newTitle, newMetaDescription, newKeywords) {
              metaKeywords = newKeywords;
              metaDescription = newMetaDescription;
              title = newTitle; 
          },
          metaTitle: function(){ return title; },
          metaDescription: function() { return metaDescription; },
          metaKeywords: function() { return metaKeywords; }
       }
    });

   app.controller('myCtrl',function($scope,$rootScope,MetaService){
      $rootScope.metaservice = MetaService;
      $rootScope.metaservice.set("Web App","desc","blah blah");
   });
</script>
 <body ng-controller="myCtrl"></body>


</html>

Upvotes: 37

Related Questions