zoukankan      html  css  js  c++  java
  • [转]angular2: including thirdparty js scripts in component

    本文转自:https://stackoverflow.com/questions/35570746/angular2-including-thirdparty-js-scripts-in-component/35570783#35570783

    Script tags in component templates are removed. A workaround is to create the script tag dynamically in ngAfterViewInit()

    See also https://github.com/angular/angular/issues/4903

    import { DOCUMENT } from '@angular/common';
    ...
    
    constructor(private @Inject(DOCUMENT) document, 
                private elementRef:ElementRef) {};
    
    ngAfterViewInit() {
      var s = this.document.createElement("script");
      s.type = "text/javascript";
      s.src = "http://somedomain.com/somescript";
      this.elementRef.nativeElement.appendChild(s);
    }
    

    See also https://stackoverflow.com/a/9413803/217408

    Adding script tags in Angular component template

    https://stackoverflow.com/questions/38088996/adding-script-tags-in-angular-component-template?noredirect=1

    23
     

    Maybe a little late to the party here, but since the above answers do not work well with Angular SSR (e.g. document is not defined server-side or document.createElement is not a function), I decided to write a version that works for Angular 4+, in both server and browser context:

    Component Implementation

    import { Renderer2, OnInit, Inject } from '@angular/core';
    import { DOCUMENT } from '@angular/platform-browser';
    
    class MyComponent implements OnInit {
    
        constructor(private _renderer2: Renderer2, @Inject(DOCUMENT) private _document) {
    
        }
    
        public ngOnInit() {
    
            let s = this._renderer2.createElement('script');
            s.type = `application/ld+json`;
            s.text = `
                {
                    "@context": "https://schema.org"
                    /* your schema.org microdata goes here */
                }
            `;
    
            this._renderer2.appendChild(this._document.body, s);
        }
    }
    

    Service Implementation

    NOTE: Services cannot use Renderer2 directly. In fact, rendering element is supposed to be done by a Component. However, you might find yourself in situation where you want to automate the creation of JSON-LD script tags on a page. A situation could be to invoke such function on route navigation change events. Hence I decided to add a version that works in a Service context.

    import { Renderer2, Inject } from '@angular/core';
    import { DOCUMENT } from '@angular/platform-browser';
    
    class MyService {
    
        constructor(@Inject(DOCUMENT) private _document) {
    
        }
    
        /**
         * Set JSON-LD Microdata on the Document Body.
         *
         * @param renderer2             The Angular Renderer
         * @param data                  The data for the JSON-LD script
         * @returns void
         */
        public setJsonLd(renderer2: Renderer2, data: any): void {
    
            let s = renderer2.createElement('script');
            s.type = `application/ld+json`;
            s.text = `${JSON.stringify(data)}`;
    
            renderer2.appendChild(this._document.body, s);
        }
    }





    The following works with Angular 5.2.7:

    The required imports are:

    import { Inject, AfterViewInit, ElementRef } from '@angular/core';
    import { DOCUMENT } from '@angular/common';
    

    Implement AfterViewInit:

    export class HeroesComponent implements AfterViewInit {
    

    If your component is implementing more that one interfaces, separate them by comma; for example:

    export class HeroesComponent implements OnInit, AfterViewInit {
    

    Pass the below arguments to constructor:

    constructor(@Inject(DOCUMENT) private document, private elementRef: ElementRef) { }
    

    Add ngAfterViewInit method of view life-cycle:

    ngAfterViewInit() {
        const s = this.document.createElement('script');
        s.type = 'text/javascript';
        s.src = '//external.script.com/script.js';
        const __this = this; //to store the current instance to call 
                             //afterScriptAdded function on onload event of 
                             //script.
        s.onload = function () { __this.afterScriptAdded(); };
        this.elementRef.nativeElement.appendChild(s);
      }
    

    Add afterScriptAdded member function.

    This function will be called after the external script is loaded successfully. So the properties or functions you want to use from external js will be accessed in the body of this function.

     afterScriptAdded() {
        const params= {
           '350px',
          height: '420px',
        };
        if (typeof (window['functionFromExternalScript']) === 'function') {
          window['functionFromExternalScript'](params);
        }
      }




    Actually There is no Angular2 way of adding a script tag to a template. but you can do some trickfirst of all you will import AfterViewInit and ElementRef from angular2 like this :

    import {Component,AfterViewInit,ElementRef} from 'Angular2/core';
    

    then you will you will implement them in your class like that :

    export class example1 implements AfterViewInit{}
    

    and here is a very simple javascript dom trick you gonna do

     export class example1 implements AfterViewInit{
     ngAfterViewInit()
     {
      var s=document.createElement("script");
      s.type="text/javascript";
      s.innerHTML="console.log('done');"; //inline script
      s.src="path/test.js"; //external script
     }
    }

    https://stackoverflow.com/questions/34140065/script-tag-in-angular2-template-hook-when-template-dom-is-loaded?noredirect=1

    I encountered the same issue, but additionally I had to load in a number of scripts, some of which could loaded in parallel, and others in series. This solution will work if you are using TypeScript 2.1 or greater, which has native support for async/await and transpiles to ES3/ES5:

    async ngAfterViewInit() {
      await this.loadScript("http://sub.domain.tld/first-script.js")
      await this.loadScript("http://sub.domain.tld/second-script.js")
    }
    
    private loadScript(scriptUrl: string) {
      return new Promise((resolve, reject) => {
        const scriptElement = document.createElement('script')
        scriptElement.src = scriptUrl
        scriptElement.onload = resolve
        document.body.appendChild(scriptElement)
      })
    }
    

    For any scripts that can be loaded in parallel, you can take advantage of Promise.all:

    async ngAfterViewInit() {
      await Promise.all([
        this.loadScript("http://sub.domain.tld/first-parallel.js"),
        this.loadScript("http://sub.domain.tld/second-parallel.js")
      ])
      await this.loadScript("http://sub.domain.tld/after-parallel.js")
    }
    

    Note: For promise rejection, you can try working with scriptElement.onerror = reject in the loadScript() function, however, I encountered some quirky behavior in this situation. If you want script to keep loading no matter what, you may want to experiment with resolving promises when onerror is called.

  • 相关阅读:
    强人教你吃自助火锅(转载)
    求职贴士:面试之十大不可说
    通过LoadRunner监控Linux的资源状况
    最美好的中秋祝福献给您
    一台电脑中招,整网均被感染9166.biz / 5y5.us Arp木马病毒专杀360独家发布
    白领把握交际的最佳时间〔转载〕
    40道题预测你能活多久
    老色狼给小色狼的32句忠告[转载]
    WINRAR 命令行语法[转载]
    <<软件性能测试与LoadRunner实战>>可以在网上和书店买到了
  • 原文地址:https://www.cnblogs.com/freeliver54/p/10364947.html
Copyright © 2011-2022 走看看