I'm followed this tutorial and tried to use the service for dynamic seo metadata. https://weluse.de/blog/angularjs-seo-finally-a-piece-of-cake.html
However, run into an issue - Seems like the service is not accessable outside of controller's view. <div ui-view></div>
Here is the service i'm trying to implement:
app.service('SeoMetaService', function() {
var metaDescription = '';
var metaKeywords = '';
var title = '';
return {
metaDescription: function() { return metaDescription; },
metaKeywords: function() { return metaKeywords; },
title: function() { return title; },
reset: function() {
metaDescription = '';
metaKeywords = '';
title = '';
},
setMetaDescription: function(newMetaDescription) {
metaDescription = newMetaDescription;
},
appendMetaKeywords: function(newKeywords) {
for(var i=0;i<newKeywords.length;i++){
if (metaKeywords === '') {
metaKeywords += newKeywords[i];
} else {
metaKeywords += ', ' + newKeywords[i];
}
}
},
setTitle: function(newTitle) { title = newTitle; }
};
});
usage in controller:
app.controller('WelcomeController',['$scope', 'SeoMetaService', function($scope, SeoMetaService) {
$(document).ready(function() {
var keywords = ["bla bla","bla bla blah"];
SeoMetaService.setTitle("title bla bla bla");
SeoMetaService.setMetaDescription("description bla bla bla");
SeoMetaService.appendMetaKeywords(keywords);
console.log(SeoMetaService.metaDescription());
console.log(SeoMetaService.metaKeywords());
});
}]);
on the main page (one-page-app), simplified:
<html ng-app="MainPage">
<head>
<title>{{SeoMetaService.title()}}</title>
<meta name="description" content="{{ SeoMetaService.metaDescription() }}">
<meta name="keywords" content="{{ SeoMetaService.metaKeywords() }}">
<base href="/">
</head>
<body>
<div ui-view></div>
</body>
So the problem is - i thought that angular services are singletons. But, after running the controller and setting the data, it doesn't appear in HTML.
How to fix/what to do?
I imagine that you defined the WelcomeController
at level of View.
So SeoMetaService
is visible only in the inner html present in the <div ui-view></div>
.
You need to define the controller WelcomeController
at level of <html>
or <head>
, because SeoMetaService
is accessible only inside the tag defining the controller WelcomeController
.
Additionally you need to remove the reference to JQuery
and expose the SeoMetaService
in the $scope
.
The code should be something like that.
The HTML:
<head ng-controller='WelcomeController'>
<title>{{SeoMetaService.title()}}</title>
<meta name="description" content="{{ SeoMetaService.metaDescription() }}">
<meta name="keywords" content="{{ SeoMetaService.metaKeywords() }}">
<base href="/">
</head>
The controller updated:
app.controller('WelcomeController',['$scope', 'SeoMetaService', function($scope, SeoMetaService) {
var keywords = ["bla bla","bla bla blah"];
SeoMetaService.setTitle("title bla bla bla");
SeoMetaService.setMetaDescription("description bla bla bla");
SeoMetaService.appendMetaKeywords(keywords);
console.log(SeoMetaService.metaDescription());
console.log(SeoMetaService.metaKeywords());
// Added to the scope SeoMetaService
$scope.SeoMetaService = SeoMetaService;
}]);
Note that you can change the content of SeoMetaService also in another controller, so for example changing a view you can update title, meta description and meta keywords reflecting the content of the new view.
Here is a possible example for the controller MyViewController
app.controller('MyViewController',['$scope', 'SeoMetaService', function($scope, SeoMetaService) {
var keywords = ["xxx","yyy"];
SeoMetaService.setTitle("title my view");
SeoMetaService.setMetaDescription("description my view");
SeoMetaService.appendMetaKeywords(keywords);
}]);
When you enter the view using the controller MyViewController
the keywords, title, meta description and meta keywords will be updated.