import { Injectable, Inject } from '@angular/core'; import { DOCUMENT } from '@angular/common'; import { Optional, RendererFactory2, ViewEncapsulation } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class SEOService { constructor( @Inject(DOCUMENT) private doc, private rendererFactory: RendererFactory2, @Inject(DOCUMENT) private document) { } createLinkForCanonicalURL(url:string, addParameters:boolean=true) { this.createLink(url,"relcan", "canonical", addParameters) } createLinkForCanonicalSearchURL(url:string, addParameters:boolean=true, ) { this.createLink(url,"relcan", "canonical", addParameters); this.createLink(url,"relnext", "next", addParameters) this.createLink(url,"relprev", "prev", addParameters) } createLinkForNextURL(url:string, addParameters:boolean=true) { this.createLink(url,"relnext", "next", addParameters) } createLinkForPrevURL(url:string, addParameters:boolean=true) { this.createLink(url,"relprev", "prev", addParameters) } createLink(url:string, id:string, relname:string, addParameters:boolean=true) { if(this.doc && (typeof this.doc.getElementById === "function" || typeof this.doc.createElement === "function") ){ if(!addParameters && url && url.indexOf("?") != -1){ url = url.substring(0,url.indexOf("?")); } if (typeof this.doc.getElementById === "function") { let currentLink: HTMLLinkElement = this.doc.getElementById(id); if(currentLink ){ currentLink.setAttribute('href', url); return ; } } if (typeof this.doc.createElement === "function") { let link: HTMLLinkElement = this.doc.createElement('link'); link.setAttribute('id', id); link.setAttribute('rel', relname); this.doc.head.appendChild(link); link.setAttribute('href', url); } }else{ 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; if (head === null) { throw new Error(' not found within DOCUMENT.'); } renderer.setAttribute(link, "rel", relname); renderer.setAttribute(link, "href", (addParameters)?url:url.split("?")[0]); renderer.setAttribute(link, "id", id); // [TODO]: get them to update the existing one (if it exists) ? renderer.appendChild(head, link); } catch (e) { console.error('Error within linkService : ', e); } } } removeLinkForNextURL() { this.removeLink("relnext", "next"); } removeLinkForPrevURL() { this.removeLink("relprev", "prev"); } removeLink( id:string, relname:string) { if(this.doc && (typeof this.doc.getElementById === "function" || typeof this.doc.createElement === "function") ){ if (typeof this.doc.getElementById === "function") { let currentLink: HTMLLinkElement = this.doc.getElementById(id); if(currentLink ){ currentLink.setAttribute('href', ""); currentLink.setAttribute('rel', ""); return ; } } } } } /* * -- LinkService -- [Temporary] * @MarkPieszak * * Similar to Meta service but made to handle 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 */ // 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(' 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); // } // } // // 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; };