json language files are not found ngx-translate angular-cli - json

My project is set up with Angular CLI, so it's built with webpack but the webpack config files are hidden.
I got two files, nl.json and fr.json, but get a 404 for both, even though it looks like it's going to the correct folder: http://localhost:4200/i18n/nl.json.
They have this structure:
{
"SEARCH_PAGE": {
"searchPerson": "Zoek een persoon",
"search": "Zoek"
}
}
In app.module:
...
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [Http]
}
}),
...
and
export function HttpLoaderFactory(http: Http) {
return new TranslateHttpLoader(http, "/i18n/", ".json");
}
I also include these in my sub module where I [try to] use the translation, with the difference of .forChild instead of .forRoot.
In my component:
constructor(translate: TranslateService) {
translate.addLangs(["nl", "fr"]);
translate.setDefaultLang('nl'); // this language will be used as a fallback when a translation isn't found in the current language
let browserLang: string = translate.getBrowserLang();
translate.use(browserLang.match(/nl|fr/) ? browserLang : 'nl');
}
Could it be something not linked to ngx-translate ?
When I use the pipe <h1>{{ 'SEARCH_PAGE.searchPerson' | translate}}</h1> I get nothing on the screen, when I use the directive <h1 translate]="'SEARCH_PAGE.searchPerson'"></h1> I get literally the string.

I had similar problem.
Everything worked fine locally but I was getting 404 errors when deployed app to Azure.
I tried to open /assets/i18n/.json in my browser and got the same error.
The issue was that .json files requred special MIME type configured on server.
The problem was resolved by adding web.config to the package.
1) create web.config file in app\src folder with following body:
<?xml version="1.0"?>
<configuration>
<system.webServer>
<staticContent>
<mimeMap fileExtension=".json" mimeType="application/json" />
</staticContent>
</system.webServer>
</configuration>
2) Include this file to the package by edditing angular.json
projects -> <your project> -> architect -> build -> options -> assets
Add src/web.config to the assets array
Example:
...
"assets": [
"src/favicon.ico",
"src/assets",
"src/web.config"
],
You can see more info here: https://devdays.com/2014/07/21/snippet-using-json-file-on-windows-iis-iis-express/

Just found the answer in #122 .
In angular-cli.json you have to include i18n in the assets array:
"apps": [
{
...
"assets": [
"assets",
"favicon.ico",
"i18n"
],
...
This works even if your i18n directory is not inside your assets directory.
EDIT: and now both the pipe and the directory work.

For anyone encountering a similar error where translation json files cannot be found by the HttpTranslateLoader, please see the following github issue:
https://github.com/ngx-translate/core/issues/921
In newer versions of Angular, Interceptors can interfere with the loading of the json asset files. The approach in the issue shows how to bypass interceptors for the translation files like this (quoted from the issue):
export function translateHttpLoaderFactory(httpBackend: HttpBackend): TranslateHttpLoader {
return new TranslateHttpLoader(new HttpClient(httpBackend));
}
...
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
deps: [HttpBackend],
useFactory: translateHttpLoaderFactory
}
}),

In my case I just change
export function HttpLoaderFactory(http: HttpClient){
return new TranslateHttpLoader(http, './assets/i18n/', '.json');}
For
export function HttpLoaderFactory(http: HttpClient){
return new TranslateHttpLoader(http, '../../assets/i18n/', '.json');}
it was only a rooting problem, so sometimes we should check the basics first.

Try to hoot default lang to translateService using APP_INITIALIZER:
import { BrowserModule } from '#angular/platform-browser';
import { NgModule, APP_INITIALIZER } from '#angular/core';
import { FormsModule, Validators, ReactiveFormsModule } from '#angular/forms';
import { HttpClientModule, HttpClient } from '#angular/common/http';
import { TranslateModule, TranslateLoader, TranslateService } from '#ngx-translate/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { RouterInputService } from './services/router-input.service';
import { Observable } from 'rxjs/Observable';
export function createTranslateLoader(http: HttpClient) {
return new TranslateHttpLoader(http, '/private/lifeinsurance/assets/', '.json');
}
export function initTranslation(translate: TranslateService) {
return () => {
translate.setDefaultLang('en');
translate.use('en');
return Promise.resolve();
};
}
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
ReactiveFormsModule,
HttpClientModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: (createTranslateLoader),
deps: [HttpClient]
}
})
],
providers: [
{
'provide': APP_INITIALIZER,
'useFactory': initTranslation,
'deps': [TranslateService],
'multi': true
},
RouterInputService
],
bootstrap: [AppComponent]
})
export class AppModule { }

Related

Problem with reading from a json file when refreshing th page Angular

I have an angular application and the client wants the path of the Backend in a json file, so he can change it easily whithout needing of another deployment.
Well i did it, but when i refresh the page or close the app and reopen it, the app don't detect the path of the backend, it is like a problem of retard or synchronisation.
This is the error in the console :
http://***/undefinedapi/Leave/GetlistLeave
This is how i did it :
The json file :
{
"ApiRoot": "http://***/"
}
How i read from the constant from the json file :
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Observable } from 'rxjs';
import { apiRoot } from '../model/model.apiRoot';
import { map } from 'rxjs/operators';
#Injectable({
providedIn: 'root'
})
export class apiRootService {
static apiRoot: string;
constructor(private http: Http) { }
public initialiseApiRoot()
{
this.http.get('./assets/apiRoot/apiRoot.json').pipe(map((response: Response) =>
<apiRoot>response.json())).subscribe(data => {
apiRootService.apiRoot = data['ApiRoot'];
})
}
}
and then i call this function in the constructor of app.component.ts like this :
this.apiRootService.initialiseApiRoot();
and change the call of the api in every servic elike this :
return this.http.get(apiRootService.apiRoot + .....
Any hlp and thanks
Well, let's suppose you're not facing a cache problem. If it isn't a cache problem, maybe it's a matter of timing.
You can try to set your apiRoot while your app is initializing (before app.component.ts is loaded). You can do that by providing an APP_INITIALIZER as described in Angular docs. If you use a factory that returns a function providing a promise, you'll delay your app initialization until your json file is loaded so you can initialize apiRoot. A factory is a useful approach because it will allow you to inject HttpClient service during initialization in the provider (you'll need it to get your json file).
You can do something like (in your app.module.ts):
...
import {APP_INITIALIZER} from '#angular/core';
...
// Angular will inject the HttpClient because you'll
// tell it that this is a dependency of this factory
// in the providers array
export function getApiRoot(http: HttpClient) {
return () => {
return this.http.get('./assets/apiRoot/apiRoot.json').pipe(
map((response: Response) => <apiRoot>response.json()),
tap((data: any) => apiRootService.apiRoot = data['ApiRoot'])
).toPromise();
};
}
...
#NgModule({
imports: [
...
HttpClientModule,
...
],
providers: [
...
{
provide: APP_INTIALIZER,
useFactory: getApiRoot,
multi: true,
deps: [HttpClient]
}
...
]
})
export class AppModule {}
because you are going with wrong approach. you are seeting url after application is initialized. Refer :- https://medium.com/voobans-tech-stories/multiple-environments-with-angular-and-docker-2512e342ab5a. this will give general idea how to achieve build once and deploy anywhere

Read the JSON file before loading the core modules

I am using angular to build my Project. I want to change the API endpoint after building the Project. For this I have created the JSON file in the assets folder and all of the service files read the data from that file. The data in the JSON file can also be changed after building the Project. But the problem is that API endpoint is required in the core.module.ts which is executed before the JSON file is loaded. So the data from the JSON file is always undefined. Is it possible to load the JSON file before the core.module.ts, so that no problem occurs.
JSON File
{
"env": {
"name": "dev"
},
"apiServer": {
"url": "/api"
}
}
app.config.ts
export class AppConfig {
constructor(private http: Http) {}
load() {
const jsonFile = `assets/config/config.${environment.name}.json`;
return new Promise<void>((resolve, reject) => {
this.http.get(jsonFile).toPromise().then((response: Response) => {
AppConfig.settings = response.json();
resolve();
}).catch((response: any) => {
reject(`Could not load file '${jsonFile}': ${JSON.stringify(response)}`);
});
});
}
}
app.module.ts
export function initializeApp(appConfig: AppConfig) {
return () => appConfig.load();
}
providers: [
AppConfig,
{ provide: APP_INITIALIZER,
useFactory: initializeApp,
deps: [AppConfig], multi: true },
{ provide: APP_BASE_HREF, useValue: '/' },
]
The APP_INITIALIZER injection token is the best way to run your code. You need to hook into the application init process and load. To do that, you have to create AppConfig in the app.module.ts file:
export function appConfigFactory(provider: AppConfig): Function {
return () => provider.load();
}
providers: [
HttpModule,
StartupService,
Title,
{
provide: APP_INITIALIZER,
useFactory:appConfigFactory,
deps: [AppConfig],
multi: true
}
So, I recommend you to read these :
https://devblog.dymel.pl/2017/10/17/angular-preload/
https://www.cicoria.com/ensuring-initializing-and-server-side-configuration-with-angular/
To understand more read this:
https://www.intertech.com/Blog/angular-4-tutorial-run-code-during-app-initialization/
https://hackernoon.com/hook-into-angular-initialization-process-add41a6b7e

Getting the error "No provider for NavController" when trying to pass data from child component to parent component

I'm trying to send data from my home.ts file to the app.component.ts file using EventEmitter and Output. But everytime I reference the home page component in my app.html I get this seemingly random error. When I remove NavController from the constructor in home.ts, the error goes away.
home.ts :
import { Component, EventEmitter, Output } from '#angular/core';
import { NavController } from 'ionic-angular';
#Component({
selector: 'page-home',
templateUrl: 'home.html',
})
export class HomePage {
message : any;
#Output() notify : EventEmitter<Object> = new EventEmitter<Object>();
constructor(public navCtrl: NavController) {
}
ionViewDidLoad(){
this.message = {"Name":"Sid", "Age":17};
this.notify.emit(this.message);
}
}
app.html :
<ion-nav [root]="rootPage"></ion-nav>
<page-home (notify)="getChildData($event)"></page-home>
app.component.ts :
import { Component, ViewChild, ViewChildren } from '#angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar } from '#ionic-native/status-bar';
import { SplashScreen } from '#ionic-native/splash-screen';
import { HomePage } from '../pages/home/home';
#Component({
templateUrl: 'app.html'
})
export class MyApp {
rootPage:any = HomePage;
constructor(platform: Platform, statusBar: StatusBar, splashScreen:
SplashScreen) {
platform.ready().then(() => {
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
statusBar.styleDefault();
splashScreen.hide();
});
}
getChildData(message){
console.log(message["Name"]);
console.log(message["Age"]);
}
}
How do I fix this error ? I need to use the NavController so I can't remove it. I want to still be able to send data from the child component to the parent component
The error is pointing out that you should provide the NavController in the providers section somewhere. This section could be in several modules of your application but the general one is the app.module.ts file.
In there you have a providers section in which you can provide services or providers for the Angular dependency injection mechanism to work appropriately.
So my first thougth would be to add the navController in the providers section of your app.module.ts file. This ensures that Angular can resolve the dependency to your NavController. Putting it in the app.module.ts file makes it having the same instance fo your navcontroller all over your application.
#NgModule({
bootstrap: [ AppComponent ],
declarations: [
...
],
imports: [
...
],
exports: [
],
providers: [
...
NavController
]
})
However, since you are using ionic, I would check out a related topic on the following url.
Ionic 2 - Runtime Error No provider for NavController

apiUser.json in _http.get() is not found

Indeed, I don't know why my url in _http.get('app/api/apiUsers') is not found while in a angular version 2.3.1 is functional but in angular version 4.0.0 it does not work.
This is my code and they are the same in both angular versions:
import { Injectable } from '#angular/core';
import { Http } from '#angular/http';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/do';
#Injectable()
export class LoginService {
constructor(private _http: Http){}
getFromApiLogin(){
console.log("I am here");
return this._http.get('app/api/apiUsers.json)
.do(x => console.log(x))
.map(res => res.json());
}
}
I assume you are using a CLI project... so it does just serve paths that you have added to the assets in the file .angular.cli.json
Try that:
"assets": [
"assets",
"favicon.ico",
"./app/api/apiUsers.json"
]

Ng2-table not working with latest Angular2 version

I am currently using Angular2 for my application and now I want to add ng2-table to my component.
ng2-Table on Git
I am getting this error and couldn't help but ask:
angular2-polyfills.js:487 Unhandled Promise rejection: Template parse errors:
Can't bind to 'colums' since it isn't a known property of 'ng-table'.
1. If 'ng-table' is an Angular component and it has 'colums' input, then
verify that it is part of this module.
2. If 'ng-table' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA"
to the '#NgModule.schema' of this component to suppress this message.
("
</div>-->
<ng-table [ERROR ->][colums]="columns" [rows]="rows" > </ng-table>
<div class="">
"): DeviceOverviewComponent#18:10 ;
Zone: <root> ; Task: Promise.then ; Value: Error: Template parse errors:(…)
In my html I got this:
<ng-table [columns]="columns" [rows]="rows" > </ng-table>
My Component is this:
import { Component } from '#angular/core';
import { Router } from '#angular/router';
import { DeviceService } from '../services/device.service';
#Component({
selector: 'device-overview',
templateUrl: 'dist/html/deviceoverview.component.html',
providers: [DeviceService],
})
export class DeviceOverviewComponent {
devices: any;
columns: any;
rows: any;
constructor(private deviceService: DeviceService, private router: Router) {
}
loadDevices() {
this.deviceService.getDevices()
.then((data) => {
this.devices = data
this.rows = this.devices
})
}
goToDevice(deviceName: string) {
this.router.navigateByUrl('/devices/' + deviceName)
}
ngOnInit() {
this.columns = [
{ title: "test", name: "id" }]
this.loadDevices();
}
}
And my app.module is this:
import { NgModule } from '#angular/core';
import { LocationStrategy, HashLocationStrategy } from '#angular/common';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule } from '#angular/forms';
import { HttpModule } from '#angular/http';
import { Ng2TableModule } from 'ng2-table/ng2-table';
import { AppComponent } from './components/app.component';
import { DeviceOverviewComponent } from './components/deviceoverview.component'
import { DeviceService } from './services/device.service';
import { routing } from './app.routing';
#NgModule({
imports: [
Ng2TableModule,
BrowserModule,
FormsModule,
HttpModule,
routing,
],
declarations: [
DeviceOverviewComponent,
AppComponent,
],
providers:
[
{provide: LocationStrategy, useClass: HashLocationStrategy},
DeviceService,
],
bootstrap: [AppComponent]
})
export class AppModule { }
Does anybody know anything about the Usage of ng2-table? Or is there a valid alternative, since the demo page/usage documentation is not available by now?
I found some alternatives, but lots of them had their last commit a long time ago, which might be a problem, since I am always using latest Angular2.
Thanks for reading and any hel is appreciated!
EDIT:
I've made it to the next step!
I needed to add
import {CUSTOM_ELEMENTS_SCHEMA} from '#angular/core'
#NgModule({ ...,
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
within my app.module.ts
Now I am getting the table header with the "test" column and the ID property of my row data is displayed correctly.
Even the demo from ng2-table didn't have that import.
I guess docs and demos arent made for newbes nowadays. :/
i see a typo in your html:
[colums]="columns"
It should be
[columns]="columns"
You're missing n
Plunker Example (I also tried it on local machine and it works)
You shouldn't use CUSTOM_ELEMENTS_SCHEMA
systemjs.config.js
map: {
...
'ng2-table': 'npm:ng2-table'
},
packages: {
...
'ng2-table': {
defaultExtension: 'js'
}
}
After long time I close this issue.
In my case I have these structure:
src
--app
-- app.module
-- TravelPlan
-- travel-plan.module
-- test.component
So, I was trying put the ng2-smart-table in app.module, but I was wrong. The correct is put in travel-plan.module.