Angular - Download json translation file from server and use it in browser - javascript

I have a json file that I download from the server, this file is managed from the server and contains translations that I use for server error messages. Is it possible to use this file and overwrite an empty json file that I have in my frontend app? Or is it reccomended to store this json inside localstorage? What's the best approach?

I'll do this on server site. So I transmit (on login as example) my current language and the server gives the response in the current language to the client.
Is this no option for you look to ngx-translate. It's a library that uses Pipes to make a multi lang app (and so much more!). Here is the NPM link.
With this you can use a custom loader which load your JSON which includes the translated texts from a given URL. Normally this url is your assets folder. But you can do it with external link like this (Here is the answer an Stackoverflow):
export class CustomLoader implements TranslateLoader {
constructor(private httpClient: HttpClient) {}
getTranslation(lang: string): Observable<any> {
const header = new HttpHeaders({
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
});
const apiAddress = 'https://xxxx.xxx.xxxx.windows.net/lang/en.json';
return this.httpClient.get(apiAddress, { headers: header});
}
}
But the new syntax you need looks a bit different. Here, in the App Module you need to use ngx-translates HttpBackend instead of Angulars HttpClient But you can read more in the official documentation of ngx-translate.
imports: [
...
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpBackend],
},
}),
],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
function HttpLoaderFactory(http: HttpBackend) {
return new MultiTranslateHttpLoader(http, [
{ prefix: './assets/i18n/', suffix: '.json' },
]);
}
Here is another good link, too.
Then we need to create our own loader to load the translations from an external API server. The custom loader needs to implement the TranslateLoader interface which has a required method getTranslation() that returns an Observable. We will put the custom loader class in a new file translate-loader.ts:
import { HttpClient } from '#angular/common/http';
import { TranslateLoader } from '#ngx-translate/core';
import { Observable } from 'rxjs';
import { environment } from '../environments/environment';
export class CustomTranslateLoader implements TranslateLoader {
constructor(private http: HttpClient) {}
getTranslation(lang: string): Observable<any> {
return this.http.get(`${environment.apiHost}/translations/${lang}`);
}
}

Related

How to properly inject provider in NestJS?

I create a Firebase provider like below(without using module file with exports and imports):
#Injectable()
export class FirebaseProvider {
public app: admin.app.App;
constructor() {
this.app = admin.initializeApp(config);
}
}
and add this provider to providers in AppModule:
providers: [AppService, FirestoreProvider, ClientService],
and in ClientModule:
providers: [CustomersService, FirestoreProvider],
so, now i want to use this provider in my ClientService, so I inject this provider via constructor like below:
constructor(
private readonly firestoreProvider: FirestoreProvider,
) {}
and now i have a problem, can somone tell me why NestJs inject me this provider more than one time and because of this firebase throw me this error:
The default Firebase app already exists. This means you called initializeApp() more than once without providing an app name as the second argument. In most cases you only need to call initializeApp() once. But if you do want to initialize multiple
apps, pass a second argument to initializeApp() to give each app a unique name.
I initialize this firebase only in this provider, so how to properly use this provider in services across the whole project?
thanks for any help!
I don't think you want to declare your FirestoreProvider in the provider:[] array of a module more than once. Try something like this:
#Module({
imports: [
FirestoreModule
],
})
export class AppModule{}
Now that you've imported the FirestoreModule, you can use it in any class that is in this AppModule. Example:
#Injectable()
export class FooService {
constructor(private firestore: FirestoreProvider) {}
}
The key here is to define your provider in its own module, then export it via the exports:[] array, and provide it via the providers:[] array of that module.
import { FirestoreProvider } from './FirestoreProvider'
#Module({
providers: [ FirestoreProvider ],
exports: [ FirestoreProvider ],
})
export class FirestoreModule{}
#Injectable()
export class FirestoreProvider {
public app: admin.app.App;
constructor() {
this.app = admin.initializeApp(config);
}
}

NestJS - how to provide services of dynamic modules

I'm struggling to figure out on how to provide services from DynamicModule to regular Modules. Pseudocode below:
app.module.ts
#Global()
#Module({
imports: [
DynamicModule.forRoot(config),
RegularModule,
],
providers: [],
exports: [],
})
export class AppModule {}
dynamic.module.ts
#Module({})
export class DynamicModule implements OnModuleInit, OnModuleDestroy {
constructor(private dynamicService: dynamicService) {}
static forRoot(config: Config): DynamicModule {
return {
module: DynamicModule,
imports: [],
providers: [
{
provide: CONFIG_TOKEN,
useValue: config,
},
DynamicService,
],
exports: [
DynamicService,
],
};
}
}
dynamic.service.ts
#Injectable()
export class DynamicService {
constructor(
#Inject(CONFIG_TOKEN) private readonly config: Config,
) {}
}
regular.module.ts
#Module({
imports: [],
providers: [RegularService, DynamicService],
exports: [RegularService],
})
export class RegularModule {}
regular.service.ts
#Injectable()
export class RegularService {
constructor(
private readonly dynamicService: DynamicService
) {}
}
Providing DynamicService to RegularModule requires to provide CONFIG_TOKEN in RegularModule as well, which seems odd and not practical in case more modules would depend on DynamicService and doesn't seem to be the correct way.
What concepts am I missing and what is correct approach to use services of a DynamicModule?
Would something as forFeature in DynamicModule method would be the right direction?
dynamic modules are modules that need some sort of context defined input, classic example is a database module that would need at least the host url and credentials, which would vary by app.
This means that when the forRoot(input) returns, you have a module just like any regular (non dynamic) module. As such, you can make use of the config value inside the dynamic module's service, export the service on the dynamic module, and then inject that service on other modules that import your dynamic module.
There is no need to also inject the config value on the service that injected the dynamicService.
If you need to have direct access to the config value inside of regularService, and that value is being shared across multiple services and modules, then you should take a look at the ConfigModule and treat that config value as env. If by some very specific reason it cant or should not be in env, then still you should create a separate module for providing this config values.

How to use Laravel as the backend for an Angular SPA app?

I would like to create a website with Angular (frontend) and Laravel (backend).
What is the best way to connect these two? How do they communicate?
What I found while searching was more than 2 years old solutions, so I am wondering if there is a preferred way to do that now.
What I do right now:
I created Model, Controller and Migration files in laravel, and in LanguagesController I call the "::all" method to get all the data from XAMPP:
public function index()
{
return response()->json(Languages::all(), 200, ['Content-Type' => 'application/json;charset=UTF-8', 'Charset' => 'utf-8'],
JSON_UNESCAPED_UNICODE);
}
After that I create route for it in api.php:
Route::get('/languages', "LanguagesController#index");
So now, I can call www.laravelfirsttry.com/api/languages to get all the data from Languages table.
In Angular, I did the following:
Create a language-service which send a request to Laravel:
private baseUrl = 'http://www.laravelfirsttry.com/api/languages';
constructor(private http: HttpClient) { }
getLanguages() {
return this.http.get(this.baseUrl);
}
Then in my component I call this service, and give its function's response to my variable then I just handle the view after that:
constructor(private languageService: LanguageService) {
this.getLanguages();
}
getLanguages(): void{
this.languageService.getLanguages()
.subscribe((res: any) => {
this.language_tabs = res;
console.log(res);
}, error => {
console.error(error);
});
}
But the problem is that when I try it, the api call takes relatively long time to finish. I load my website, all the content is loaded, but the main component is not visible until the call is finished. I think this does not look good, and I think I did something wrong.
Summary: I created one API in laravel, then I call this API in Angular, and its quite slow. What is the best way to make an Angular application with Laravel backend?
First, you need HttpClientModule to the imports array of your AppModule,
something like this.
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { HttpClientModule } from '#angular/common/http';
import { AppComponent } from './app.component';
#NgModule({
imports: [
BrowserModule,
HttpClientModule
],
declarations: [
AppComponent
],
bootstrap: [AppComponent]
})
export class AppModule { }
Then import httpClient in your component and add it to the constructor
import { HttpClient } from '#angular/common/http';
Then you can call API with code like this.
this.http.get<any>('http://www.laravelfirsttry.com/api/languages').subscribe(data => {
console.log(data);
// do any operations with your data.
})
As a pre-requisite Please make sure that your backend Laravel API is working fine.

unable to retrieve json data from assets folder using angular

what i want : i have a config file where it contains some urls in .json file stored in asset folder now instead of loading environments.prod or .ts i want to load my json file config and basing on that i want run my application
what i did
below is my json file which i placed asset folder
{
"baseUrl": "https://jsonplaceholder.typicode.com/",
"baseUrl2": "https://reqres.in/api/users"
}
now i created a ConfigServiceService.ts fpr storing config file
public _config: Object;
constructor(public http:Http) { }
getData(){
debugger;
return this.http.get("./assets/config.json").pipe(map(res => res.json()));
}
after this i create a ServiceProviderService.ts for calling the service file
configData:any;
constructor(public http:Http,public config:ConfigServiceService) {
}
jsonData(){
debugger;
return this.configData;
}
ngOnInit(){
debugger;
this.config.getData().subscribe(res =>{
console.log(res);
this.configData = res;
});
}
now i am calling the app.component.ts
title = 'sample';
constructor(public serv :ServiceProviderService){
this.serv.jsonData();
}
now my issue is i am not able to get the json data and if i am putting the logic which is there is ngoninit in ServiceProviderService.ts file if put it in constructor then i am getting undefined
note : here if there are more that once url then each url is distributed to various seperate service file suppose base1 url for 1 service file ans base2 url for another file how can i achieve that
To access the assets folder. Make sure angular.json has a reference under
architect --> build -->options to the directory where the file is stored:
"assets": [
"src/favicon.ico",
"src/assets"
],
Try giving it an absolute url and it should work
Here, give this a try:
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Injectable()
export class ConfigService {
constructor(private http: HttpClient) { }
getData() {
return this.http.get('/assets/config.json');
}
}
Here's a Working Sample StackBlitz for your ref.
In Angular only components have lifecycle hooks (like ngOnInit, ngOnDestroy etc), services haven't. In services you should use their constructor instead.

asp.net Core Angular4 angular/common/http not found

My question sounds similar to Cannot find the '#angular/common/http' module and Error loading #angular/common/http - angular 2 but the problem is a bit different:
I am using Angular 4.3.5 and I am trying to read data from a Web API. (This API puts out JSON data and is using SignalR and .net Core).
I have followed several tutorials and came up with this code for the class that will actually contact the service:
import 'rxjs/add/operator/map';
import { HttpClient, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '#angular/common/http';
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs/Observable';
import { Configuration } from './Configuration.js';
#Injectable()
export class DataService {
private actionUrl: string;
constructor(private http: HttpClient, private configuration: Configuration) {
this.actionUrl = configuration.serviceUrl;
}
//public getAll<T>(): Observable<T> {
// return this.http.get<T>(this.actionUrl);
//}
public getSingle<T>(id: number): Observable<T> {
return this.http.get<T>(this.actionUrl + id);
}
}
#Injectable()
export class CustomInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (!req.headers.has('Content-Type')) {
req = req.clone({ headers: req.headers.set('Content-Type', 'application/json') });
}
req = req.clone({ headers: req.headers.set('Accept', 'application/json') });
console.log(JSON.stringify(req.headers));
return next.handle(req);
}
}
Now, building this project (I am using Visual Studio 2017 Enterprise) and running a gulp task to transpile the .ts to .js works just fine, so do all the intellisense-tooltips - the IDE does recognize the existance of those things.
But if I open it up in a browser (doesnt matter if firefox, edge or chrome) I get the following error:
zone.js:958 GET http://localhost:3966/libs/#angular/common/bundles/common.umd.js/http 404 (Not Found)
If I edit the transpiled javascript file by hand and write common-http.umd.js there, the file is found. (This is the reason why at the top I import Configuration.js instead of Configuration - it doesnt seem to want to automatically resolve the suffix, like in some tutorials).
I hope I am not too vague, since this is my first Time asking something publically. Also I was not able to find an answer in the given questions.
Well, I found a solution, for anybody who is curious why this and similar problems exist:
I had to edit my systemjs file and add this line:
'#angular/common/http': 'npm:#angular/common/bundles/common-http.umd.js',
and it works!

Categories