Jak dynamicznie ładować zewnętrzne skrypty w Angular?


150

Mam taki moduł, który komponuje zewnętrzną bibliotekę wraz z dodatkową logiką bez dodawania <script>tagu bezpośrednio do index.html:

import 'http://external.com/path/file.js'
//import '../js/file.js'

@Component({
    selector: 'my-app',
    template: `
        <script src="http://iknow.com/this/does/not/work/either/file.js"></script>
        <div>Template</div>`
})
export class MyAppComponent {...}

Zauważyłem, że importspecyfikacja ES6 jest statyczna i rozwiązana podczas transpilacji TypeScript, a nie w czasie wykonywania.

W każdym razie, aby był konfigurowalny, aby plik.js był ładowany z CDN lub folderu lokalnego? Jak powiedzieć Angularowi 2, aby ładował skrypt dynamicznie?


Odpowiedzi:


61

Jeśli używasz system.js, możesz użyć System.import()w czasie wykonywania:

export class MyAppComponent {
  constructor(){
    System.import('path/to/your/module').then(refToLoadedModule => {
      refToLoadedModule.someFunction();
    }
  );
}

Jeśli używasz pakietu webpack, możesz w pełni wykorzystać jego solidną obsługę dzielenia kodu dzięki require.ensure:

export class MyAppComponent {
  constructor() {
     require.ensure(['path/to/your/module'], require => {
        let yourModule = require('path/to/your/module');
        yourModule.someFunction();
     }); 
  }
}

1
Wygląda na to, że muszę użyć modułu ładującego konkretnie w komponencie. Cóż, to dobrze System, bo myślę , że to przyszłość programu ładującego.
CallMeLaNN

6
TypeScript Plugin for Sublime Textnie jest zadowolony z Systemw kodzie TypeScript: Cannot find name 'System'ale nie ma błędu podczas transpilacji i uruchamiania. Zarówno plik skryptu, jak Angular2i Systemplik skryptu już zostały dodane do index.html. W każdym razie do i uczynić szczęśliwą wtyczki? importSystem
CallMeLaNN

1
ale co jeśli nie używasz system.js!
Murhaf Sousli,

2
@drewmoore Nie pamiętam, dlaczego to powiedziałem, require()/ importpowinno teraz działać dobrze jako twoja odpowiedź, +1
Murhaf Sousli

9
Z tego, co wiem, te opcje nie działają w przypadku skryptów w Internecie, tylko w przypadku plików lokalnych. To nie wydaje się odpowiadać na zadane pytanie.
WillyC

139

Możesz użyć następującej techniki, aby dynamicznie ładować skrypty JS i biblioteki na żądanie w swoim projekcie Angular.

script.store.ts będzie zawierać ścieżkę do skryptu lokalnie lub na serwerze zdalnym oraz nazwę, która będzie używana do dynamicznego ładowania skryptu

 interface Scripts {
    name: string;
    src: string;
}  
export const ScriptStore: Scripts[] = [
    {name: 'filepicker', src: 'https://api.filestackapi.com/filestack.js'},
    {name: 'rangeSlider', src: '../../../assets/js/ion.rangeSlider.min.js'}
];

script.service.ts to usługa do wstrzykiwania, która obsługuje ładowanie skryptu, kopiowanie script.service.tsw takiej postaci, w jakiej jest

import {Injectable} from "@angular/core";
import {ScriptStore} from "./script.store";

declare var document: any;

@Injectable()
export class ScriptService {

private scripts: any = {};

constructor() {
    ScriptStore.forEach((script: any) => {
        this.scripts[script.name] = {
            loaded: false,
            src: script.src
        };
    });
}

load(...scripts: string[]) {
    var promises: any[] = [];
    scripts.forEach((script) => promises.push(this.loadScript(script)));
    return Promise.all(promises);
}

loadScript(name: string) {
    return new Promise((resolve, reject) => {
        //resolve if already loaded
        if (this.scripts[name].loaded) {
            resolve({script: name, loaded: true, status: 'Already Loaded'});
        }
        else {
            //load script
            let script = document.createElement('script');
            script.type = 'text/javascript';
            script.src = this.scripts[name].src;
            if (script.readyState) {  //IE
                script.onreadystatechange = () => {
                    if (script.readyState === "loaded" || script.readyState === "complete") {
                        script.onreadystatechange = null;
                        this.scripts[name].loaded = true;
                        resolve({script: name, loaded: true, status: 'Loaded'});
                    }
                };
            } else {  //Others
                script.onload = () => {
                    this.scripts[name].loaded = true;
                    resolve({script: name, loaded: true, status: 'Loaded'});
                };
            }
            script.onerror = (error: any) => resolve({script: name, loaded: false, status: 'Loaded'});
            document.getElementsByTagName('head')[0].appendChild(script);
        }
    });
}

}

Wstrzykuj to w ScriptServicedowolnym miejscu i ładuj biblioteki js w ten sposób

this.script.load('filepicker', 'rangeSlider').then(data => {
    console.log('script loaded ', data);
}).catch(error => console.log(error));

7
To działa znakomicie. Zmniejsza rozmiar początkowego ładowania o ponad 1 MB - mam wiele bibliotek!
Our_Benefactors

2
Wygląda na to, że odezwałem się za wcześnie. To rozwiązanie NIE działa w iOS Safari.
Our_Benefactors

po załadowaniu skryptu sprawdź, czy dołącza się on do nagłówka twojego domu
Rahul Kumar.

Być może nie wstrzykuję prawidłowo, ale dostajęthis.script.load is not a function
Towelie

Dzięki. To działa, ale mój skrypt (animacja w tle) jest ładowany w każdym innym komponencie. Chcę, aby był ładowany tylko na moim pierwszym komponencie (jest to strona logowania). Co mogę zrobić, żeby to osiągnąć? Dzięki
Joel Azevedo,

47

To może zadziałać. Ten kod dynamicznie dołącza <script>znacznik do headpliku HTML po kliknięciu przycisku.

const url = 'http://iknow.com/this/does/not/work/either/file.js';

export class MyAppComponent {
    loadAPI: Promise<any>;

    public buttonClicked() {
        this.loadAPI = new Promise((resolve) => {
            console.log('resolving promise...');
            this.loadScript();
        });
    }

    public loadScript() {
        console.log('preparing to load...')
        let node = document.createElement('script');
        node.src = url;
        node.type = 'text/javascript';
        node.async = true;
        node.charset = 'utf-8';
        document.getElementsByTagName('head')[0].appendChild(node);
    }
}

1
Dzięki, człowiek pracował dla mnie. Możesz teraz załadować go podczas ładowania strony również za pomocą metody ngonit. Więc kliknięcie przycisku nie jest wymagane.
Niraj

Używam w ten sam sposób ... ale nie działa dla mnie. czy możesz mi pomóc w tym samym? this.loadJs ("ścieżka do pliku javascript"); public loadjs (plik) {let node = document.createElement ('skrypt'); node.src = plik; node.type = 'text / javascript'; node.async = true; node.charset = 'utf-8'; document.getElementsByTagName ('head') [0] .appendChild (węzeł); }
Mitesh Shah

Czy próbujesz to zrobić po kliknięciu czy po załadowaniu strony? Czy możesz powiedzieć nam więcej o wyniku lub błędzie?
ng-darren

witam, próbowałem to zaimplementować i działa dobrze, ale new Promisenie został rozwiązany. Czy możesz mi powiedzieć Promise, czy muszę cokolwiek importować?
user3145373 ツ

Cześć, nie zaimportowałem niczego specjalnego, gdy używam Promise.
ng-darren

23

Zmodyfikowałem odpowiedź @rahul kumars, aby zamiast tego używała Observables:

import { Injectable } from "@angular/core";
import { Observable } from "rxjs/Observable";
import { Observer } from "rxjs/Observer";

@Injectable()
export class ScriptLoaderService {
    private scripts: ScriptModel[] = [];

    public load(script: ScriptModel): Observable<ScriptModel> {
        return new Observable<ScriptModel>((observer: Observer<ScriptModel>) => {
            var existingScript = this.scripts.find(s => s.name == script.name);

            // Complete if already loaded
            if (existingScript && existingScript.loaded) {
                observer.next(existingScript);
                observer.complete();
            }
            else {
                // Add the script
                this.scripts = [...this.scripts, script];

                // Load the script
                let scriptElement = document.createElement("script");
                scriptElement.type = "text/javascript";
                scriptElement.src = script.src;

                scriptElement.onload = () => {
                    script.loaded = true;
                    observer.next(script);
                    observer.complete();
                };

                scriptElement.onerror = (error: any) => {
                    observer.error("Couldn't load script " + script.src);
                };

                document.getElementsByTagName('body')[0].appendChild(scriptElement);
            }
        });
    }
}

export interface ScriptModel {
    name: string,
    src: string,
    loaded: boolean
}

1
Zapomniałeś ustawić asyncto true.
Will Huang

Mam pytanie, kiedy dołączamy skrypt i nawigujemy między trasami, powiedzmy, że załadowałem skrypt na stronie głównej, przeglądam stronę około i wróciłem do domu, czy istnieje sposób na przywrócenie obecnego skryptu? Czy chciałbym usunąć wcześniej załadowany plik i załadować go ponownie? Dziękuję bardzo
d123546

@ d123546 Tak, jeśli chcesz, jest to możliwe. Ale musiałbyś napisać logikę, która usuwa tag skryptu. Zajrzyj tutaj: stackoverflow.com/questions/14708189/…
Joel

Dzięki Joel, ale czy jest sposób na usunięcie funkcji zainicjowanych przez skrypt? Obecnie mam problem w moim projekcie angular4, ponieważ ładuję skrypt inicjalizujący suwak jquery, więc gdy pierwsza trasa ładuje się poprawnie, ale kiedy nawiguję na inną trasę i wracam do mojej trasy, skrypt jest ładowany dwukrotnie i suwak już się nie ładuje :( Czy możesz mi doradzić w tej sprawie
d123546

1
W wierszu jest błąd private scripts: {ScriptModel}[] = [];. Powinno byćprivate scripts: ScriptModel[] = [];
Chris Haines

20

Jeszcze inną opcją byłoby wykorzystanie scriptjspakietu do tego celu

umożliwia ładowanie zasobów skryptów na żądanie z dowolnego adresu URL

Przykład

Zainstaluj pakiet:

npm i scriptjs

i definicje typów dlascriptjs :

npm install --save @types/scriptjs

Następnie $script.get()metoda importu :

import { get } from 'scriptjs';

i na koniec załaduj zasób skryptu, w naszym przypadku bibliotekę Google Maps:

export class AppComponent implements OnInit {
  ngOnInit() {
    get("https://maps.googleapis.com/maps/api/js?key=", () => {
        //Google Maps library has been loaded...
    });
  }
}

Próbny


Dzięki za udostępnienie, ale jak można dodać dodatkową właściwość z adresem URL, np. Async defer? Czy możesz mi pomóc, jak załadować ten skrypt za pomocą powyższej biblioteki? <script type = 'text / javascript' src = ' bing.com/api/maps/mapcontrol?branch=release ' async defer> </script>
Pushkar Rathod

Ponieważ temat jest ten sam, skaczę odpowiedź tylko tutaj
Pushkar Rathod

Świetnie, ale zamiast npm install --save @ types / scriptjs, powinno to być npm install --save-dev @ types / scriptjs (lub po prostu npm i -D @ types / scriptjs)
Youness Houdass

18

W swoim pliku możesz dynamicznie ładować wiele skryptów, takich jak ten component.ts:

 loadScripts() {
    const dynamicScripts = [
     'https://platform.twitter.com/widgets.js',
     '../../../assets/js/dummyjs.min.js'
    ];
    for (let i = 0; i < dynamicScripts.length; i++) {
      const node = document.createElement('script');
      node.src = dynamicScripts[i];
      node.type = 'text/javascript';
      node.async = false;
      node.charset = 'utf-8';
      document.getElementsByTagName('head')[0].appendChild(node);
    }
  }

i wywołaj tę metodę wewnątrz konstruktora,

constructor() {
    this.loadScripts();
}

Uwaga: Aby więcej skryptów było ładowanych dynamicznie, dodaj je do dynamicScriptstablicy.


3
Muszę powiedzieć, że wygląda to prosto, ale działa dobrze, bardzo łatwe do wdrożenia :-)
Pierre

3
Problem z tym typem wstrzykiwania skryptów polega na tym, że skoro Angular jest SPA, te skrypty zasadniczo pozostają w pamięci podręcznej przeglądarki nawet po usunięciu znacznika script z DOM.
j4rey,

1
Świetna odpowiedź! Zaoszczędziłem dzień, działa z Angular 6 i 7. Przetestowano!
Nadeeshan Herath

Aby wysłać dane do zewnętrznego js i pobrać dane z zewnętrznego js, ​​wywołaj tę funkcję na app.component.ts i użyj deklaracji var d3Sankey: any na dowolnym poziomie funkcji komponentu modułu. To działa.
gnganpath

5

Zrobiłem ten fragment kodu z nowym interfejsem API modułu renderującego

 constructor(private renderer: Renderer2){}

 addJsToElement(src: string): HTMLScriptElement {
    const script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = src;
    this.renderer.appendChild(document.body, script);
    return script;
  }

A potem nazwij to tak

this.addJsToElement('https://widgets.skyscanner.net/widget-server/js/loader.js').onload = () => {
        console.log('SkyScanner Tag loaded');
} 

StackBlitz


4

Mam dobry sposób na dynamiczne ładowanie skryptów! Teraz używam w moim projekcie ng6, echarts4 (> 700Kb), ngx-echarts3. kiedy używam ich w dokumentach ngx-echarts, potrzebuję importu echarts w angular.json: "scripts": ["./ node_modules / echarts / dist / echarts.min.js"], więc w module logowania, strona podczas ładowania skryptów .js, to jest duży plik! Nie chcę tego.

Myślę więc, że kątowe ładuje każdy moduł jako plik, mogę wstawić program rozpoznawania nazw routera, aby wstępnie załadować js, a następnie rozpocząć ładowanie modułu!

// PreloadScriptResolver.service.js

/**动态加载js的服务 */
@Injectable({
  providedIn: 'root'
})
export class PreloadScriptResolver implements Resolve<IPreloadScriptResult[]> {
  // Here import all dynamically js file
  private scripts: any = {
    echarts: { loaded: false, src: "assets/lib/echarts.min.js" }
  };
  constructor() { }
  load(...scripts: string[]) {
    const promises = scripts.map(script => this.loadScript(script));
    return Promise.all(promises);
  }
  loadScript(name: string): Promise<IPreloadScriptResult> {
    return new Promise((resolve, reject) => {
      if (this.scripts[name].loaded) {
        resolve({ script: name, loaded: true, status: 'Already Loaded' });
      } else {
        const script = document.createElement('script');
        script.type = 'text/javascript';
        script.src = this.scripts[name].src;
        script.onload = () => {
          this.scripts[name].loaded = true;
          resolve({ script: name, loaded: true, status: 'Loaded' });
        };
        script.onerror = (error: any) => reject({ script: name, loaded: false, status: 'Loaded Error:' + error.toString() });
        document.head.appendChild(script);
      }
    });
  }

  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<IPreloadScriptResult[]> {
   return this.load(...route.routeConfig.data.preloadScripts);
  }
}

Następnie w submodule-routing.module.ts , zaimportuj ten PreloadScriptResolver:

const routes: Routes = [
  {
    path: "",
    component: DashboardComponent,
    canActivate: [AuthGuardService],
    canActivateChild: [AuthGuardService],
    resolve: {
      preloadScripts: PreloadScriptResolver
    },
    data: {
      preloadScripts: ["echarts"]  // important!
    },
    children: [.....]
}

Ten kod działa dobrze i obiecuje, że: Po załadowaniu pliku js rozpocznie się ładowanie modułu! ten Resolver może być używany w wielu routerach


Czy mógłbyś udostępnić kod interfejsu IPreloadScriptResult?
Mehul Bhalala

3

Uniwersalne rozwiązanie Angular; Musiałem poczekać, aż określony element pojawi się na stronie, zanim załaduję skrypt, aby odtworzyć wideo.

import {Inject, Injectable, PLATFORM_ID} from '@angular/core';
import {isPlatformBrowser} from "@angular/common";

@Injectable({
  providedIn: 'root'
})
export class ScriptLoaderService {

  constructor(
    @Inject(PLATFORM_ID) private platformId: Object,
  ) {
  }

  load(scriptUrl: string) {
    if (isPlatformBrowser(this.platformId)) {
      let node: any = document.createElement('script');
      node.src = scriptUrl;
      node.type = 'text/javascript';
      node.async = true;
      node.charset = 'utf-8';
      document.getElementsByTagName('head')[0].appendChild(node);
    }
  }
}

1
To w jakiś sposób wydaje się podejrzane
Mustafa

2

Rozwiązanie @ rahul-kumar działa dobrze dla mnie, ale chciałem wywołać moją funkcję javascript w moim skrypcie

foo.myFunctions() // works in browser console, but foo can't be used in typescript file

Naprawiłem to, deklarując to w moim maszynopisie:

import { Component } from '@angular/core';
import { ScriptService } from './script.service';
declare var foo;

A teraz mogę zadzwonić do foo w dowolnym miejscu w moim pliku typekryptu


jeśli importuję wiele skryptów foo, foo1, foo2 i wiem tylko w czasie wykonywania, jak dynamicznie wykonać deklarację?
natrayan

2

W moim przypadku załadowałem oba pliki jsi css visjsużywając powyższej techniki - która działa świetnie. Wzywam nową funkcję zngOnInit()

Uwaga: nie udało mi się go załadować, po prostu dodającznacznik<script>i<link>do pliku szablonu html.

loadVisJsScript() {
  console.log('Loading visjs js/css files...');
  let script = document.createElement('script');
  script.src = "../../assets/vis/vis.min.js";
  script.type = 'text/javascript';
  script.async = true;
  script.charset = 'utf-8';
  document.getElementsByTagName('head')[0].appendChild(script);    
	
  let link = document.createElement("link");
  link.type = "stylesheet";
  link.href = "../../assets/vis/vis.min.css";
  document.getElementsByTagName('head')[0].appendChild(link);    
}


Chcę załadować plik CSS z zewnętrznego źródła internetowego. Obecnie mam do czynienia z błędem „Nie można załadować lokalnego zasobu” .. Proszę zasugerować.
Karan

Próbowałem w ten sposób. Mimo że działa dobrze w przypadku plików skryptów, nie działa w przypadku arkuszy stylów
118218

2

Cześć, możesz użyć Renderer2 i elementRef z zaledwie kilkoma wierszami kodu:

constructor(private readonly elementRef: ElementRef,
          private renderer: Renderer2) {
}
ngOnInit() {
 const script = this.renderer.createElement('script');
 script.src = 'http://iknow.com/this/does/not/work/either/file.js';
 script.onload = () => {
   console.log('script loaded');
   initFile();
 };
 this.renderer.appendChild(this.elementRef.nativeElement, script);
}

onloadfunkcja może być używany do wywołania funkcji skryptowych po załadowaniu skryptu, jest to bardzo przydatne, gdy trzeba wykonać połączenia w ngOnInit ()


1

@ d123546 Napotkałem ten sam problem i uruchomiłem go teraz, używając ngAfterContentInit (Lifecycle Hook) w komponencie takim jak ten:

import { Component, OnInit, AfterContentInit } from '@angular/core';
import { Router } from '@angular/router';
import { ScriptService } from '../../script.service';

@Component({
    selector: 'app-players-list',
    templateUrl: './players-list.component.html',
    styleUrls: ['./players-list.component.css'],
    providers: [ ScriptService ]
})
export class PlayersListComponent implements OnInit, AfterContentInit {

constructor(private router: Router, private script: ScriptService) {
}

ngOnInit() {
}

ngAfterContentInit() {
    this.script.load('filepicker', 'rangeSlider').then(data => {
    console.log('script loaded ', data);
    }).catch(error => console.log(error));
}

1
import { Injectable } from '@angular/core';
import * as $ from 'jquery';

interface Script {
    src: string;
    loaded: boolean;
}

@Injectable()
export class ScriptLoaderService {
    public _scripts: Script[] = [];

    /**
     * @deprecated
     * @param tag
     * @param {string} scripts
     * @returns {Promise<any[]>}
     */
    load(tag, ...scripts: string[]) {
        scripts.forEach((src: string) => {
            if (!this._scripts[src]) {
                this._scripts[src] = { src: src, loaded: false };
            }
        });

        const promises: any[] = [];
        scripts.forEach(src => promises.push(this.loadScript(tag, src)));

        return Promise.all(promises);
    }

    /**
     * Lazy load list of scripts
     * @param tag
     * @param scripts
     * @param loadOnce
     * @returns {Promise<any[]>}
     */
    loadScripts(tag, scripts, loadOnce?: boolean) {
        debugger;
        loadOnce = loadOnce || false;

        scripts.forEach((script: string) => {
            if (!this._scripts[script]) {
                this._scripts[script] = { src: script, loaded: false };
            }
        });

        const promises: any[] = [];
        scripts.forEach(script => promises.push(this.loadScript(tag, script, loadOnce)));

        return Promise.all(promises);
    }

    /**
     * Lazy load a single script
     * @param tag
     * @param {string} src
     * @param loadOnce
     * @returns {Promise<any>}
     */
    loadScript(tag, src: string, loadOnce?: boolean) {
        debugger;
        loadOnce = loadOnce || false;

        if (!this._scripts[src]) {
            this._scripts[src] = { src: src, loaded: false };
        }

        return new Promise((resolve, _reject) => {
            // resolve if already loaded
            if (this._scripts[src].loaded && loadOnce) {
                resolve({ src: src, loaded: true });
            } else {
                // load script tag
                const scriptTag = $('<script/>')
                    .attr('type', 'text/javascript')
                    .attr('src', this._scripts[src].src);

                $(tag).append(scriptTag);

                this._scripts[src] = { src: src, loaded: true };
                resolve({ src: src, loaded: true });
            }
        });
    }

    reloadOnSessionChange() {
        window.addEventListener('storage', function(data) {
            if (data['key'] === 'token' && data['oldValue'] == null && data['newValue']) {
                document.location.reload();
            }
        });
    }
}

0

próbka może być

plik script-loader.service.ts

import {Injectable} from '@angular/core';
import * as $ from 'jquery';

declare let document: any;

interface Script {
  src: string;
  loaded: boolean;
}

@Injectable()
export class ScriptLoaderService {
public _scripts: Script[] = [];

/**
* @deprecated
* @param tag
* @param {string} scripts
* @returns {Promise<any[]>}
*/
load(tag, ...scripts: string[]) {
scripts.forEach((src: string) => {
  if (!this._scripts[src]) {
    this._scripts[src] = {src: src, loaded: false};
  }
});

let promises: any[] = [];
scripts.forEach((src) => promises.push(this.loadScript(tag, src)));

return Promise.all(promises);
}

 /**
 * Lazy load list of scripts
 * @param tag
 * @param scripts
 * @param loadOnce
 * @returns {Promise<any[]>}
 */
loadScripts(tag, scripts, loadOnce?: boolean) {
loadOnce = loadOnce || false;

scripts.forEach((script: string) => {
  if (!this._scripts[script]) {
    this._scripts[script] = {src: script, loaded: false};
  }
});

let promises: any[] = [];
scripts.forEach(
    (script) => promises.push(this.loadScript(tag, script, loadOnce)));

return Promise.all(promises);
}

/**
 * Lazy load a single script
 * @param tag
 * @param {string} src
 * @param loadOnce
 * @returns {Promise<any>}
 */
loadScript(tag, src: string, loadOnce?: boolean) {
loadOnce = loadOnce || false;

if (!this._scripts[src]) {
  this._scripts[src] = {src: src, loaded: false};
}

return new Promise((resolve, reject) => {
  // resolve if already loaded
  if (this._scripts[src].loaded && loadOnce) {
    resolve({src: src, loaded: true});
  }
  else {
    // load script tag
    let scriptTag = $('<script/>').
        attr('type', 'text/javascript').
        attr('src', this._scripts[src].src);

    $(tag).append(scriptTag);

    this._scripts[src] = {src: src, loaded: true};
    resolve({src: src, loaded: true});
  }
 });
 }
 }

i użytkowania

pierwsze wstrzyknięcie

  constructor(
  private _script: ScriptLoaderService) {
  }

następnie

ngAfterViewInit()  {
this._script.loadScripts('app-wizard-wizard-3',
['assets/demo/default/custom/crud/wizard/wizard.js']);

}

lub

    this._script.loadScripts('body', [
  'assets/vendors/base/vendors.bundle.js',
  'assets/demo/default/base/scripts.bundle.js'], true).then(() => {
  Helpers.setLoading(false);
  this.handleFormSwitch();
  this.handleSignInFormSubmit();
  this.handleSignUpFormSubmit();
  this.handleForgetPasswordFormSubmit();
});
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.