Using angular 3.17
For changing url enable HTML5 in your config file.
$locationProvider
.html5Mode(true)
and on your index page add this in your header:
<base href="/">
HTML 5 is needed to update your url. # is old according to Google and Google recommends not using pre-render unless it serves a greater purpose than just seo.
This is the directive I used:
app.directive('someDirective',['$location', function(location){
return {
restrict: 'EA',
controller: 'someController',
link: function(scope,element,attrs){
scope.$on('event-change', function(event, data){
//some function prepares new url
var newUrl = someController.someFunction();
location.url(url);
})
}
}
$location is passed in the directive to allow the use of location in the link function.
scope.$on is used to trigger the directive. This is helpful because often your directives will load before your data is ready (could be the issue you're facing please post more code).
someController is passing a factory as a dependent. The factory broadcasts the scope.$on event. I often set the data in the factory at the beginning of page load, once promises have been resolved. This allows me to avoid using $watch or $observe.
I've had no problems creating dynamic meta description. Url was a pain to figure out. Here is a directive example:
app.directive('someDirective', function(){
return {
scope: {
metaDescription: '@'
},
controller: 'someController',
replace: true,
template: '<meta name="description" content="{{metaDescription}}">',
link: function(scope,element, attrs){
scope.$on('some-event', function(event, data){
//some controller function that prepares and returns dynamic meta description
var newMeta = someController.someFunction();
//assigns value in your template
scope.metaDescription = newMeta;
})
}
});
My understanding is using @ isolates the scope to inside the directive...meaning you have to pass the value from the DOM or create the value inside the directive.
And finally in your index.html file add the directive inside the header:
<header>
<some-directive></some-directive>
</header>
Your output should be your template with the meta description inside. If this doesn't work then you could try adding a watch or observe in the link function. Or you could broadcast right from the parent controller and use that broadcast event to activate your scope.$on.