Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

append link amphtml to head in angular app

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?

like image 455
Dmitry Avatar asked Jan 19 '18 19:01

Dmitry


2 Answers

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

like image 182
Alexandra Avatar answered Sep 27 '22 23:09

Alexandra


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;
      };
like image 43
Dmitry Avatar answered Sep 28 '22 00:09

Dmitry