I have a working angular universal app and I have amp version of a specific page.
To make amp page reachable I have to add into page's <head>
this tag
<link rel="amphtml" href="https://www.example.com/url/to/amp/document.html">
So I need something similar to MetaService.
My question is how can I do this in a specific component of angular 5 app?
A more concise version of such a service would be this:
import { Inject, Injectable } from '@angular/core';
import { DOCUMENT } from '@angular/common';
@Injectable()
export class LinkService {
constructor(@Inject(DOCUMENT) private doc: Document) { }
createLink() {
let link: HTMLLinkElement = this.doc.createElement('link');
link.setAttribute('rel', 'amphtml');
link.setAttribute('href', 'https://www.example.com/url/to/amp/document.html');
this.doc.head.appendChild(link);
}
}
Source: https://www.concretepage.com/angular/angular-title-service-and-canonical-url
I was able to do this by creating the service using the code from this comment https://github.com/angular/angular/issues/15776#issuecomment-352695731
Here's the code from this comment:
/*
* -- LinkService -- [Temporary]
* @MarkPieszak
* Added removeTag by @DominicBoettger
* Similar to Meta service but made to handle <link> creation for SEO purposes
* -- NOTE: Soon there will be an overall DocumentService within Angular that handles Meta/Link everything
*/
import { Injectable, Optional, RendererFactory2, ViewEncapsulation, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/platform-browser';
@Injectable()
export class LinkService {
constructor(
private rendererFactory: RendererFactory2,
@Inject(DOCUMENT) private document
) {
}
/**
* Inject the State into the bottom of the <head>
*/
addTag(tag: LinkDefinition, forceCreation?: boolean) {
try {
const renderer = this.rendererFactory.createRenderer(this.document, {
id: '-1',
encapsulation: ViewEncapsulation.None,
styles: [],
data: {}
});
const link = renderer.createElement('link');
const head = this.document.head;
const selector = this._parseSelector(tag);
if (head === null) {
throw new Error('<head> not found within DOCUMENT.');
}
Object.keys(tag).forEach((prop: string) => {
return renderer.setAttribute(link, prop, tag[prop]);
});
// [TODO]: get them to update the existing one (if it exists) ?
renderer.appendChild(head, link);
} catch (e) {
console.error('Error within linkService : ', e);
}
}
removeTag(attrSelector: string) {
if (attrSelector) {
try {
const renderer = this.rendererFactory.createRenderer(this.document, {
id: '-1',
encapsulation: ViewEncapsulation.None,
styles: [],
data: {}
});
const head = this.document.head;
if (head === null) {
throw new Error('<head> not found within DOCUMENT.');
}
const linkTags = this.document.querySelectorAll('link[' + attrSelector + ']');
for (const link of linkTags) {
renderer.removeChild(head, link);
}
} catch (e) {
console.log('Error while removing tag ' + e.message);
}
}
}
private _parseSelector(tag: LinkDefinition): string {
// Possibly re-work this
const attr: string = tag.rel ? 'rel' : 'hreflang';
return `${attr}="${tag[attr]}"`;
}
}
export declare type LinkDefinition = {
charset?: string;
crossorigin?: string;
href?: string;
hreflang?: string;
media?: string;
rel?: string;
rev?: string;
sizes?: string;
target?: string;
type?: string;
} & {
[prop: string]: string;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With