Pipe Translater in Html Element - html

So, dont know if anyone can help me. I have the below line of code in html :
<ion-item class="item-style">
<ion-label>{{ 'SettingsPage.ChangeLanguage' | translate }}</ion-label>
<ion-select [(ngModel)]="language" (ionChange)="onLanguageChange();" cancelText={{cancelText}} okText={{okText}}>
<ion-select-option value="en">{{ 'SettingsPage.English' | translate }}</ion-select-option>
<ion-select-option value="mt">{{ 'SettingsPage.Maltese' | translate }}</ion-select-option>
</ion-select>
</ion-item>
and the following methods in the .ts :
onLanguageChange() {
this.translate.use(this.language);
console.log(this.language);
this.globalVariableService.languageChanged = true;
this.globalVariableService.setCurrentLanguage(this.language);
this.storage.set('Language', this.language).then(() => {
this.sectorDataServiceProvider.populateSectorData().then(data => {
console.log('this.sectorInfo ', this.sectorDataServiceProvider.sectorInfo);
});
});
this.setOkAndCancelText();
}
setOkAndCancelText() {
if (this.language === 'en') {
this.cancelText = 'Cancel';
this.okText = 'OK';
} else if (this.language === 'mt') {
this.cancelText = 'Le';
this.okText = 'Iva';
}
}
I wish to remove the s setOkAndCancelText() which is being used to fill the cancelText={{cancelText}} parameter when the language changes within the app, and have something similar to:
<p [innerHTML]="'TermsOfUsePage.Header' | translate"></p>
Any ideas how i can make this possible please?

Instead of reliaing on libraries, you can create your custom service and add your local strings i.e key and value as following:
#Injectable({
providedIn: 'root'
})
export class LocalizationService {
localizedStrings: any;
constructor() {
this.localizedStrings = {
en: {
SettingsPage: {
cancelText: 'Cancel'
}
},
mt: {
SettingsPage: {
cancelText: 'Le'
}
}
}
}
getResource(keyString: string, workingLanguage: string): Promise<string> {
return new Promise((resolve, reject) => {
let resourceValue = null;
if(this.localizedStrings[workingLanguage].hasOwnProperty(keyString)) {
resourceValue = this.localizedStrings[workingLanguage][keyString];
} else {
resourceValue = this.getPropertyByKeyPath(this.localizedStrings[workingLanguage], keyString);
// if(!resourceValue) {
// debugger;
// }
}
if(resourceValue) {
resolve(resourceValue);
} else {
resolve(keyString);
}
});
}
private getPropertyByKeyPath(targetObj, keyPath) {
var keys = keyPath.split('.');
if(keys.length == 0) return undefined;
keys = keys.reverse();
var subObject = targetObj;
while(keys.length) {
var k = keys.pop();
if(!subObject.hasOwnProperty(k)) {
return undefined;
} else {
subObject = subObject[k];
}
}
return subObject;
}
}
Note that it is flexible, you can go deeper in objects. Now simply create a pipe for this service:
import { Pipe } from '#angular/core';
import { LocalizationService } from '../shared/localization.service';
#Pipe({
name:"translate"
})
export class LocalizedResourcePipe {
constructor(private localizationService: LocalizationService) {
}
transform(resourceKey: string, workingLanguage: string) {
return new Promise((resolve, reject) => {
if(!resourceKey) {
resolve();
} else {
this.localizationService.getResource(resourceKey, workingLanguage)
.then((value) => {
resolve(value);
});
}
});
}
}
Now simply call it in your HTML:
<ion-select [(ngModel)]="language" (ionChange)="onLanguageChange();" cancelText={{'SettingsPage.cancelText' | translate: 'en' | async}} okText={{'SettingsPage.cancelText' | translate: 'en' | async}}>
You can could make the the language parameter dynamic as well and in pipe, give it a default value. anyway here is the way to call it for your other language:
<ion-select [(ngModel)]="language" (ionChange)="onLanguageChange();" cancelText={{'SettingsPage.cancelText' | translate: 'mt' | async}} okText={{'SettingsPage.cancelText' | translate: 'mt' | async}}>

We have done it in following ways:
Installed the following packages:
"#ngx-translate/core": "11.0.1"
"#ngx-translate/http-loader": "4.0.0",
In app.module.js, add the following in imports:
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: AppHttpLoaderFactory,
deps: [HttpClient]
}
}),
export function AppHttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http, Environment.frontend('/assets/i18n/'), '.json');
}
Here we have kept our en.json file under i18n folder where all key values of text are there.
After this you can use it in html template:
<ion-select [(ngModel)]="language" (ionChange)="onLanguageChange();" cancelText={{'cancel.text' | translate }} okText={{okText}/>
Here cancel.text is a key in en.json file.

Try this stackblitz example
Translate Service
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Injectable()
export class TranslateService {
data: any = {};
constructor(private http: HttpClient) { }
use(lang: string): Promise<{}> {
return new Promise<{}>((resolve, reject) => {
const langPath = `assets/languageFiles/${lang || 'en'}.json`;
this.http.get<{}>(langPath).subscribe(
translation => {
this.data = Object.assign({}, translation || {});
resolve(this.data);
},
error => {
this.data = {};
resolve(this.data);
}
);
});
}
}
Translate Pipe
import { Pipe, PipeTransform } from '#angular/core';
import { TranslateService } from './translate.service';
#Pipe({
name: 'translate',
pure:false
})
export class TranslatePipe implements PipeTransform {
constructor(private translate: TranslateService) {}
transform(key: any): any {
return this.translate.data[key] || key;
}
}

Related

Type 'Observable<DataListeItem[]>' is not assignable to type 'DataListeItem[]'

Full error message:
"Type 'Observable' is not assignable to type 'DataListeItem[]'.
Property 'includes' is missing in type 'Observable'."
I'm using material Table Schematic and now I want to fill the list from my Rest service.
data-liste-datasource.ts
import { DataSource } from '#angular/cdk/collections';
import { MatPaginator, MatSort } from '#angular/material';
import { map } from 'rxjs/operators';
import { Observable, of as observableOf, merge } from 'rxjs';
import { AuthService } from '../auth.service';
export interface DataListeItem {
name: string;
id: number;
email: string;
number: number;
}
export class DataListeDataSource extends DataSource<DataListeItem> {
data: DataListeItem[] = this.authservice.GetUser(); <-- error here!
constructor(private paginator: MatPaginator, private sort: MatSort, private authservice: AuthService) {
super();
}
connect(): Observable<DataListeItem[]> {
const dataMutations = [
observableOf(this.data),
this.paginator.page,
this.sort.sortChange
];
this.paginator.length = this.data.length;
return merge(...dataMutations).pipe(map(() => {
return this.getPagedData(this.getSortedData([...this.data]));
}));
}
disconnect() { }
private getPagedData(data: DataListeItem[]) {
const startIndex = this.paginator.pageIndex * this.paginator.pageSize;
return data.splice(startIndex, this.paginator.pageSize);
}
private getSortedData(data: DataListeItem[]) {
if (!this.sort.active || this.sort.direction === '') {
return data;
}
return data.sort((a, b) => {
const isAsc = this.sort.direction === 'asc';
switch (this.sort.active) {
case 'name': return compare(a.name, b.name, isAsc);
case 'email': return compare(a.email, b.email, isAsc);
case 'id': return compare(+a.id, +b.id, isAsc);
case 'number': return compare(+a.number, +b.number, isAsc);
default: return 0;
}
});
}
}
function compare(a, b, isAsc) {
return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
}
auth.service.ts
import { Injectable } from '#angular/core';
import { HttpHeaders, HttpClient } from '../../node_modules/#angular/common/http';
import { Observable } from '../../node_modules/rxjs';
import { DataListeItem } from './data-liste/data-liste-datasource';
#Injectable({
providedIn: 'root'
})
export class AuthService {
constructor(private http: HttpClient) { }
GetUser(): Observable<DataListeItem[]> {
return this.http.get<DataListeItem[]>("DataListeItem.online");
}
So all in all how to I make a call to my REST and get the list shown.
Should I make the call directly in " data-liste-datasource.ts" or should that be in the service.
thanks for reading
You need to use Observable<DataListeItem[]> instead of DataListeItem[].
data: Observable<DataListeItem[]> = this.authservice.GetUser();

TypeError: Cannot read property 'map' of undefined with Angular v6

For some reason the response JSON is not mapping correctly
Here is my html.
profile-search.component.html
<h3>Enter Username</h3>
<input (keyup)="search($event.target.value)" id="name" placeholder="Search"/>
<ul>
<li *ngFor="let package of packages$ | async">
<b>{{package.name}} v.{{package.repos}}</b> -
<i>{{package.stars}}</i>`enter code here`
</li>
</ul>
Here is component that the html pulls from.
profile-search.component.ts
import { Component, OnInit } from '#angular/core';
import { Observable, Subject } from 'rxjs';
import { debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators';
import { NpmPackageInfo, PackageSearchService } from './profile-search.service';
#Component({
selector: 'app-package-search',
templateUrl: './profile-search.component.html',
providers: [ PackageSearchService ]
})
export class PackageSearchComponent implements OnInit {
withRefresh = false;
packages$: Observable<NpmPackageInfo[]>;
private searchText$ = new Subject<string>();
search(packageName: string) {
this.searchText$.next(packageName);
}
ngOnInit() {
this.packages$ = this.searchText$.pipe(
debounceTime(500),
distinctUntilChanged(),
switchMap(packageName =>
this.searchService.search(packageName, this.withRefresh))
);
}
constructor(private searchService: PackageSearchService) { }
toggleRefresh() { this.withRefresh = ! this.withRefresh; }
}
Service that component pulls from.
profile-search.service.ts
import { Injectable, Input } from '#angular/core';
import { HttpClient, HttpHeaders, HttpParams } from '#angular/common/http';
import { Observable, of } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { HttpErrorHandler, HandleError } from '../http-error-handler.service';
export interface NpmPackageInfo {
name: string;
}
export const searchUrl = 'https://api.github.com/users';
const httpOptions = {
headers: new HttpHeaders({
'x-refresh': 'true'
})
};
function createHttpOptions(packageName: string, refresh = false) {
// npm package name search api
// e.g., http://npmsearch.com/query?q=dom'
const params = new HttpParams({ fromObject: { q: packageName } });
const headerMap = refresh ? {'x-refresh': 'true'} : {};
const headers = new HttpHeaders(headerMap) ;
return { headers, params };
}
#Injectable()
export class PackageSearchService {
private handleError: HandleError;
constructor(
private http: HttpClient,
httpErrorHandler: HttpErrorHandler) {
this.handleError = httpErrorHandler.createHandleError('HeroesService');
}
search (packageName: string, refresh = false): Observable<NpmPackageInfo[]> {
// clear if no pkg name
if (!packageName.trim()) { return of([]); }
// const options = createHttpOptions(packageName, refresh);
// TODO: Add error handling
return this.http.get(`${searchUrl}/${packageName}`).pipe(
map((data: any) => {
return data.results.map(entry => ({
name: entry.any[0],
} as NpmPackageInfo )
)
}),
catchError(this.handleError('search', []))
);
}
}
I have tried to alter
return this.http.get(`${searchUrl}/${packageName}`).pipe(
map((data: any) => {
return data.results.map(entry => ({
name: entry.any[0],
} as NpmPackageInfo )
)
to
login: data.login, and login: entry.login but keep getting the below error.
http-error-handler.service.ts:33 TypeError: Cannot read property 'map'
of undefined
at MapSubscriber.project (profile-search.service.ts:49)
at MapSubscriber.push../node_modules/rxjs/_esm5/internal/operators/map.js.MapSubscriber._next
(map.js:75)
at MapSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next
(Subscriber.js:93)
at MapSubscriber.push../node_modules/rxjs/_esm5/internal/operators/map.js.MapSubscriber._next
(map.js:81)
at MapSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next
(Subscriber.js:93)
at FilterSubscriber.push../node_modules/rxjs/_esm5/internal/operators/filter.js.FilterSubscriber._next
(filter.js:85)
at FilterSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next
(Subscriber.js:93)
at MergeMapSubscriber.push../node_modules/rxjs/_esm5/internal/operators/mergeMap.js.MergeMapSubscriber.notifyNext
(mergeMap.js:136)
at InnerSubscriber.push../node_modules/rxjs/_esm5/internal/InnerSubscriber.js.InnerSubscriber._next
(InnerSubscriber.js:20)
at InnerSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next
(Subscriber.js:93)
results in data.results is probably undefined, check that the data object matches the schema you're expecting it to.
map working on array but this.http.get(${searchUrl}/${packageName}) return object not array.
so data.results is undefined.
This is how I converted my object into an array, if anyone has a better way of doing please let me know.
return this.http.get(`${searchUrl}/${packageName}`).pipe(
map((data: any) => {
console.log(data);
var profile = Object.keys(data).map(function(key) {
return [(key) + ': ' + data[key]];
}
);
console.log(profile);
data = profile;
return data;
}),
catchError(this.handleError<Error>('search', new Error('OOPS')))
);
}
}
I fixed this issue by eliminating ".results"
from
.map((data: any) => this.convertData(data.results))
to
.map((data: any) => this.convertData(data))
To avoid the error, change
map((items) => items.map
to
map((items) => items?.map
Then set your result set as an empty array:
this.list = data ?? [];
PS: Used with Angular 14. In older versions you may need to change last one to data ? data : []

Error: Cannot find module "./../providers/auth-service" [duplicate]

I am trying to create Login/SignUp in ionic angular 3.3.0.
I get the error Cannot find module '../providers/auth-service/auth-service'. in the login.ts file. Please Help!
auth-service.ts
import { Injectable } from '#angular/core';
import { Http } from '#angular/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
/*
Generated class for the AuthServiceProvider provider.
See https://angular.io/docs/ts/latest/guide/dependency-injection.html
for more info on providers and Angular 2 DI.
*/
export class User {
name: string;
email: string;
constructor(name: string, email: string) {
this.name = name;
this.email = email;
}
}
#Injectable()
export class AuthServiceProvider {
currentUser: User;
public login(credentials) {
if (credentials.email === null || credentials.password === null) {
return Observable.throw("Please insert credentials");
} else {
return Observable.create(observer => {
// At this point make a request to your backend to make a real check!
let access = (credentials.password === "pass" && credentials.email === "email");
this.currentUser = new User('ian', 'ianlikono#gmail.com');
observer.next(access);
observer.complete();
});
}
}
public register(credentials) {
if (credentials.email === null || credentials.password === null) {
return Observable.throw("Please insert credentials");
} else {
// At this point store the credentials to your backend!
return Observable.create(observer => {
observer.next(true);
observer.complete();
});
}
}
public getUserInfo() : User {
return this.currentUser;
}
public logout() {
return Observable.create(observer => {
this.currentUser = null;
observer.next(true);
observer.complete();
});
}
}
login.ts
import { Component } from '#angular/core';
import { NavController, AlertController, LoadingController, Loading, IonicPage } from 'ionic-angular';
import { AuthServiceProvider } from '../providers/auth-service/auth-service';
#IonicPage()
#Component({
selector: 'page-login',
templateUrl: 'login.html',
})
export class LoginPage {
loading: Loading;
registerCredentials = { email: '', password: '' };
constructor(private nav: NavController, private auth: AuthServiceProvider, private alertCtrl: AlertController, private loadingCtrl: LoadingController) { }
public createAccount() {
this.nav.push('RegisterPage');
}
public login() {
this.showLoading()
this.auth.login(this.registerCredentials).subscribe(allowed => {
if (allowed) {
this.nav.setRoot('HomePage');
} else {
this.showError("Access Denied");
}
},
error => {
this.showError(error);
});
}
showLoading() {
this.loading = this.loadingCtrl.create({
content: 'Please wait...',
dismissOnPageChange: true
});
this.loading.present();
}
showError(text) {
this.loading.dismiss();
let alert = this.alertCtrl.create({
title: 'Fail',
subTitle: text,
buttons: ['OK']
});
alert.present(prompt);
}
}
ScreenShot Program structure:
From your project structure, your login.ts is inside login folder, and login folder is inside pages folder.
So in order to reach providers folder, you need to write
'../../providers/auth-service/auth-service'
This should move you out of two folders which should solve the issue.
If you are using VS Code, install the plugin called "Typescript Hero" and "Typescript Toolbox", will help you with your imports.
Actually "Typescript Toolbox" shows a lightbulb when you focus your cursor on an imported element and you can select from the lightbulb the import. Very usefull.

Disable Angular 2 sanitization

I've seen a few answers to this question and tried all of them, but it still isn't working. I'm kinda trying to write a CMS in angular 2; so a backend where someone puts HTML and a frontend that renders said HTML. I am able to display some HTML with DomSanitizer.bypassSecurityTrustHtml() but not others. For example, I am able to add an <img class="center" src=""> but a <button md-button>test</button> is rendered as a plain HTML button. I also have a LessonComponent w/a lesson selector, but it isn't rendered at all on the page, I do see the <lesson></lesson> HTML in the inspector.
How (if possible) do I display components on the page from a DB? Code below:
lesson.ts
import { Component, Inject, Input, SecurityContext } from '#angular/core';
import { MdDialog, MD_DIALOG_DATA } from '#angular/material';
import { Lesson, LessonService } from '../lesson.service';
import { DomSanitizer, SafeHtml} from '#angular/platform-browser';
#Component({
selector: 'lesson',
templateUrl: './lesson.html',
styleUrls: ['./lesson.scss']
})
export class LessonComponent {
#Input() lessonID: number = 0;
#Input() questionID: string = '';
lesson: Lesson;
constructor(public service: LessonService, public dialog: MdDialog, private sanitizer: DomSanitizer) { }
getLesson(): object {
if(!this.service.getLesson(this.lessonID)) { return {}; }
let lesson = this.service.getLesson(this.lessonID)['pages'].filter(lesson => {
return lesson['id'] === this.questionID;
})[0];
if(lesson && lesson['buttons']) {
this.service.buttons = lesson['buttons'];
} else {
this.service.buttons = [];
}
lesson['test'] = this.sanitizer.bypassSecurityTrustHtml(lesson['content']);
return lesson;
}
doClick(btnID) {
let button = this.getLesson()['buttons'].filter(btn => {
return btn['id'] === btnID;
})[0];
this.dialog.open(ExtraDialog, { data: button['content'] });
}
}
#Component({
selector: 'extra-dialog',
template: `{{data}}`
})
export class ExtraDialog {
constructor(#Inject(MD_DIALOG_DATA) public data: any) {}
}
lesson.html
<div *ngIf="!getLesson()" >
Error: Lesson {{lessonID}} -> question {{questionID}} is not a known lesson or question. Please click <a routerLink="/lesson/1">here</a> to go to the first lesson.
</div>
<div *ngIf="getLesson() && getLesson()['buttons']">
<span *ngFor="let button of getLesson()['buttons']">
<button md-mini-fab (click)="doClick(button.id)"><md-icon>{{button.icon}}</md-icon></button>
</span>
</div>
<div *ngIf="getLesson()">
<h2>{{getLesson()['title']}}</h2>
<p [innerHTML]="getLesson()['test']"></p>
</div>
lesson.service.ts
import { Injectable } from '#angular/core';
import { AngularFireDatabase, FirebaseObjectObservable } from 'angularfire2/database';
export class Lesson {
constructor(public id: number, public pages: Object[]) { }
}
#Injectable()
export class LessonService {
private lessons: Lesson[] = [];
public buttons: object[];
constructor(public db: AngularFireDatabase) {
this.db.object('/lessons', { preserveSnapshot: true }).subscribe(lessons => {
this.lessons = [];
lessons.forEach(lesson => {
let pages = [];
if(lesson.val()['pages']) {
Object.keys(lesson.val()['pages']).forEach(key => {
let page = {
id: key,
title: lesson.val()['pages'][key]['title'],
content: lesson.val()['pages'][key]['content']
};
let buttons = lesson.val()['pages'][key]['buttons'];
if(buttons) {
page['buttons'] = [];
Object.keys(buttons).forEach(key => {
page['buttons'].push({
content: buttons[key]['content'],
icon: buttons[key]['icon'],
id: key
});
});
}
pages.push(page);
});
}
this.lessons.push(new Lesson(
lesson.key,
pages
));
});
});
}
getLessons() { return this.lessons; }
getLesson(id: number): Lesson {
return this.lessons.filter(lesson => {
return lesson['id'] == id;
})[0];
}
}

setting google map API key from angular 2 service

Im using sebastine google map in angular 2 application. I know AgmCoreModule.forRoot({ apiKey: "xxxxxxxx" }) can be used to set API key but I need to set API key from a angular service in my #component is it possible....help needed.
You may need to update provide a custom provider like this { provide: MapsAPILoader, useClass: CustomLazyAPIKeyLoader } where you have imported AgmCoreModule.
And in CustomLazyAPIKeyLoader class override the load method.
import { Injectable, Inject } from '#angular/core';
import { Http, Response, Headers, RequestOptions } from '#angular/http';
import { MapsAPILoader, LAZY_MAPS_API_CONFIG, LazyMapsAPILoaderConfigLiteral, GoogleMapsScriptProtocol } from 'angular2-google-maps/core';
import { DocumentRef, WindowRef } from 'angular2-google-maps/core/utils/browser-globals';
#Injectable()
export class CustomLazyAPIKeyLoader extends MapsAPILoader {
private _scriptLoadingPromise: Promise<void>;
private _config: LazyMapsAPILoaderConfigLiteral;
private _windowRef: WindowRef;
private _documentRef: DocumentRef;
constructor( #Inject(LAZY_MAPS_API_CONFIG) config: any, w: WindowRef, d: DocumentRef, private http: Http) {
super();
this._config = config || {};
this._windowRef = w;
this._documentRef = d;
}
load(): Promise<void> {
if (this._scriptLoadingPromise) {
return this._scriptLoadingPromise;
}
const script = this._documentRef.getNativeDocument().createElement('script');
script.type = 'text/javascript';
script.async = true;
script.defer = true;
const callbackName: string = `angular2GoogleMapsLazyMapsAPILoader`;
this.http.get("getKey")
.subscribe((res: any) => {
this._config.apiKey = res._body;
script.src = this._getScriptSrc(callbackName);
this._documentRef.getNativeDocument().body.appendChild(script);
});
this._scriptLoadingPromise = new Promise<void>((resolve: Function, reject: Function) => {
(<any>this._windowRef.getNativeWindow())[callbackName] = () => { console.log("loaded"); resolve(); };
script.onerror = (error: Event) => { reject(error); };
});
return this._scriptLoadingPromise;
}
private _getScriptSrc(callbackName: string): string {
let protocolType: GoogleMapsScriptProtocol =
(this._config && this._config.protocol) || GoogleMapsScriptProtocol.HTTPS;
let protocol: string;
switch (protocolType) {
case GoogleMapsScriptProtocol.AUTO:
protocol = '';
break;
case GoogleMapsScriptProtocol.HTTP:
protocol = 'http:';
break;
case GoogleMapsScriptProtocol.HTTPS:
protocol = 'https:';
break;
}
const hostAndPath: string = this._config.hostAndPath || 'maps.googleapis.com/maps/api/js';
const queryParams: { [key: string]: string | Array<string> } = {
v: this._config.apiVersion || '3',
callback: callbackName,
key: this._config.apiKey,
client: this._config.clientId,
channel: this._config.channel,
libraries: this._config.libraries,
region: this._config.region,
language: this._config.language
};
const params: string =
Object.keys(queryParams)
.filter((k: string) => queryParams[k] != null)
.filter((k: string) => {
// remove empty arrays
return !Array.isArray(queryParams[k]) ||
(Array.isArray(queryParams[k]) && queryParams[k].length > 0);
})
.map((k: string) => {
// join arrays as comma seperated strings
let i = queryParams[k];
if (Array.isArray(i)) {
return { key: k, value: i.join(',') };
}
return { key: k, value: queryParams[k] };
})
.map((entry: { key: string, value: string }) => { return `${entry.key}=${entry.value}`; })
.join('&');
return `${protocol}//${hostAndPath}?${params}`;
}
}
this.http.get("getKey")
.subscribe((res: any) => {
this._config.apiKey = res._body;
script.src = this._getScriptSrc(callbackName);
this._documentRef.getNativeDocument().body.appendChild(script);
});
Above code will make it async.
I added an resolver to get the API key
import { Resolve, ActivatedRouteSnapshot } from '#angular/router'
import { Injectable, Inject } from '#angular/core'
import { SomeService } from '../services/some.service'
import { LazyMapsAPILoaderConfigLiteral, LAZY_MAPS_API_CONFIG } from '#agm/core'
import { Observable, of } from 'rxjs'
import { map, catchError } from 'rxjs/operators'
#Injectable()
export class GoogleMapAPiResolver implements Resolve<boolean> {
constructor(
private someService: SomeService,
#Inject(LAZY_MAPS_API_CONFIG)
private config: LazyMapsAPILoaderConfigLiteral
) {}
resolve(router: ActivatedRouteSnapshot): Observable<boolean> {
return this.someService.getGoogleMapApiKey().pipe(
catchError(error => {
return of(false)
}),
map(response => {
this.config.apiKey = response
return true
})
)
}
}
The SomeService consume an endpoint that return the Key
you have put the API key in the app.module.ts under the #NgModule
and make sure to enable Maps JavaScript API in the google cloud console
https://console.cloud.google.com/apis/library/maps-backend.googleapis.com
Thanks!
#NgModule({
imports: [
BrowserModule,
FormsModule,
AgmCoreModule.forRoot({
// please get your own API key here:
// https://developers.google.com/maps/documentation/javascript/get-api-key?hl=en
apiKey: 'API_KEY'
})
],
declarations: [ AppComponent, HelloComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }