I have this in a service- I18nProviderService:
createTranslationProviders(response) {
const locale = 'de';
let translationProvider: any;
translationProvider = [{
provide: TRANSLATIONS,
useValue: response
},
{
provide: TRANSLATIONS_FORMAT,
useValue: 'xlf'
},
{
provide: LOCALE_ID,
useValue: locale
}
];
return translationProvider;
}
getTranslationProvider() {
this.getTranslationFile()
.subscribe(
(response: Response) => this.createTranslationProviders(response),
(error) => console.log(error)
);
}
and this in my app.module.ts
export function startupServiceFactory(myService: I18nProviderService): Function {
return () => myService.getTranslationProvider();
}
#NgModule({
declarations: [
],
imports: [
BrowserModule,
ReactiveFormsModule,
HttpModule,
NguiAutoCompleteModule
],
providers: [I18nProviderService,
{
provide: APP_INITIALIZER,
useFactory: (myService: I18nProviderService) => () => myService.getTranslationProvider(),
deps: [I18nProviderService],
multi: true
},
],
bootstrap: [AppComponent]
})
export class AppModule {}
Why is the TRANSLATIONS_FORMAT, LOCALE_ID and TRANSLATIONS not mapped correctly. Means, if I trace the LOCALE_ID in my app.component.ts it has the default value.. not "de". I like to load my xlf translation file before app is init.
Related
I would like use provider value defined in other module. Here is example:
app.module.ts
...
import { ThemeModule } from '../shared/modules/theme/theme.module';
...
#NgModule({
declarations: [
RootComponent,
LoginScreenComponent,
],
imports: [
BrowserModule.withServerTransition({ appId: 'serverApp' }),
BrowserAnimationsModule,
AppRoutingModule,
ConfigModule,
ThemeModule,
....
],
providers: [
...
{ provider: "THEME_NAME", useValue: "VALUE" },
],
bootstrap: [RootComponent]
})
export class MDMToolModule {}
theme.module.ts
import { NgModule } from '#angular/core';
import { ThemeService } from './services/ThemeService';
#NgModule({
imports: [],
declarations: [],
providers: [
{provide: "ThemeService", useFactory: (THEME_NAME) => {
return new ThemeService(THEME_NAME)
}},
],
exports: []
})
export class ThemeModule {}
Is there possibility to pass VALUE defied not in module like above example (THEME NAME)?
if you're providing value in root module then it will be available to all other modules too so you can then simply ask for that value using Inject decorator like this:
#Injectable()
export class ThemeService {
constructor(#Inject("THEME_NAME") theme: string) {}
}
otherwise you can import your MDMToolModule inside ThemeModule though judging by the code you provided I'm assuming this MDMToolModule is your root module,
you can also use Injection Token to avoid using those magic strings like this:
const ThemeName = new InjectionToken("token to inject theme name");
and then use it inside theme.module.ts
#NgModule({
providers: [
{ provide: ThemeName, useValue: "DarkKnight" },
ThemeService
]
})
export class ThemeModule {}
theme.service.ts
#Injectable()
export class ThemeService {
constructor(#Inject(ThemeName) theme: string) {}
}
I am getting this error while while doing npm run serve:ssr
my app.module.ts looks like this:
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule.withServerTransition({ appId: 'serverApp' }),
HttpClientModule,
AppRoutingModule,
],
providers: [ProductService,
{provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true}
],
bootstrap: [AppComponent]
})
export class AppModule { }
My home.component.ts looks like this:
constructor(private productService: ProductService) { }
ngOnInit(): void {
this.productService.getHomeData().subscribe(
(data) => {
console.log(data);
},
(error) => {
console.log(error);
}
);
}
my product.service looks like this:
#Injectable()
export class ProductService {
getHomeData(): Observable<any> {
return "this.data";
}
}
Kindly help me fix this issue
ERROR TypeError: this.productService.getHomeData is not a function
at HomeComponent.ngOnInit
i have this config for my site :
import { InjectionToken } from '#angular/core';
import { HttpHeaders } from '#angular/common/http';
export let APP_CONFIG = new InjectionToken<IAppConfig>('app.config');
export interface IAppConfig {
apiEndpoint: string;
headersOptions: HttpHeaders;
}
export const AppConfig: IAppConfig = {
apiEndpoint: 'https://localhost:44354/',
headersOptions : new HttpHeaders({ 'Content-Type': 'application/json' }),
};
and i need use the core.module for using the config :
#NgModule({
declarations: [],
imports: [
CommonModule,
ToastrModule.forRoot()
],
exports: [],
providers: [
{
provide: APP_CONFIG,
useValue: AppConfig,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: RequestInterceptor, multi: true
}
],
})
export class CoreModule {
constructor( #Optional() #SkipSelf() core: CoreModule) {
if (core) {
throw new Error("CoreModule should be imported ONLY in AppModule.");
}
}
}
i using the core.module in app.module .
this my app.module :
#NgModule({
declarations: [
AppComponent,
TopHeaderComponent
],
imports: [
BrowserModule,
HttpClientModule,
SharedModule,
ReactiveFormsModule,
AppRoutingModule,
ToastrModule.forRoot(),
BrowserAnimationsModule,
FormsModule,
CoreModule,
NgZorroAntdModule
],
providers:[{ provide: NZ_I18N, useValue: en_US }],
bootstrap: [AppComponent]
})
export class AppModule { }
now i need to use the AppConfig in my service :
constructor(httpClient: HttpClient, #Inject(APP_CONFIG) private appConfig: IAppConfig) {
super(httpClient);
}
but it show me this error :
Uncaught (in promise): NullInjectorError: StaticInjectorError(AppModule)[[object Object]]:
whats the problem ? how can i solve this problem???
Modify your core module like the following (Remove multi: true)
#NgModule({
declarations: [],
imports: [
CommonModule,
ToastrModule.forRoot()
],
exports: [],
providers: [
{
provide: APP_CONFIG,
useValue: AppConfig //multi: true -> Remove here
},
{
provide: HTTP_INTERCEPTORS,
useClass: RequestInterceptor,
multi: true
}
],
})
export class CoreModule {
constructor( #Optional() #SkipSelf() core: CoreModule) {
if (core) {
throw new Error("CoreModule should be imported ONLY in AppModule.");
}
}
}
Then you can inject in your service as below:
#Injectable()
export class MainService {
constructor(#Inject(APP_CONFIG) private appConfig: IAppConfig) { }
getEndPoint(): string {
alert(this.appConfig.apiEndpoint);
return this.appConfig.apiEndpoint;
}
}
Stackblitz Here
I use i18n on my own component library, but it's not working
in my module
// AoT requires an exported function for factories
export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}
#NgModule({
declarations: [myLibraryModuleComponent],
imports: [
CommonModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
})
],
exports: [myLibraryModuleComponent, TranslateModule]
})
export class myLibraryModule { }
I got
http://localhost:4200/assets/i18n/en.json
not found. It's not the good path
Are you using aot?
if yes, as per the documentation, you must use an exported function instead of an inline function
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: (createTranslateLoader),
deps: [HttpClient]
}
})
Notice the createTranslateLoader between the parenthesis.
if no, try this:
export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http);
}
I want to use 2 interceptor globally (httpInterceptorProviders,
jwtInterceptorProviders) but it not working in my lazy modules.
I have CoreModule and X lazy load modules. The weird part is that I have an autogenerated code by swagger generator(http services) this calls being intercepted but when I use custom http services interceptor not intercept this requests.
Index.ts where I get the providers
/** Http interceptor providers in outside-in order */
export const httpInterceptorProviders = [
{ provide: HTTP_INTERCEPTORS, useClass: HttpErrorInterceptor, multi: true }
];
export const jwtInterceptorProviders = [
{ provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true }
];
CoreModule, I import my interceptors in providers
#NgModule({
imports: [
// angular
CommonModule,
HttpClientModule,
// ngrx
StoreModule.forRoot(reducers, { metaReducers }),
StoreRouterConnectingModule.forRoot(),
EffectsModule.forRoot([AuthEffects, GoogleAnalyticsEffects]),
environment.production
? []
: StoreDevtoolsModule.instrument({
name: "Angular NgRx Material Starter"
}),
// 3rd party
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
}),
ApiModule.forRoot(() => {
return new Configuration({
basePath: `${environment.HOST}:${environment.PORT}`,
apiKeys: { Authorization: "" }
});
})
],
declarations: [],
providers: [
LocalStorageService,
AuthGuardService,
AnimationsService,
TitleService,
// retryHttpInterceptorProviders,
{ provide: ErrorHandler, useClass: AppErrorHandler },
httpInterceptorProviders,
jwtInterceptorProviders,
{ provide: RouterStateSerializer, useClass: CustomSerializer },
{
provide: HAMMER_LOADER,
useValue: () => new Promise(() => {})
},
AnalyticsService,
LayoutService,
StateService,
PetsServiceWithUpload
],
exports: [TranslateModule]
})
export class CoreModule {
constructor(
#Optional()
#SkipSelf()
parentModule: CoreModule
) {
if (parentModule) {
throw new Error("CoreModule is already loaded. Import only in AppModule");
}
}
}
export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(
http,
`${environment.i18nPrefix}/assets/i18n/`,
".json"
);
}
AppModule
#NgModule({
declarations: [AppComponent, NavigationComponent, ErrorsComponent],
imports: [
BrowserAnimationsModule,
BrowserModule,
SharedModule,
AppRoutingModule,
AuthModule,
ThemeModule.forRoot(),
CoreModule
],
bootstrap: [AppComponent]
})
export class AppModule {}
Interceptor
#Injectable()
export class JwtInterceptor implements HttpInterceptor {
private isRefreshing = false;
private refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(null);
constructor(private injector: Injector,
private localstorage: LocalStorageService,
private authService: AuthService,
private store: Store<AppState>, ) { }
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
const tokenInfo = this.localstorage.getItem(AUTH_KEY);
if (tokenInfo) {
request = this.addToken(request, tokenInfo.token);
}
console.log('TCL: JwtInterceptor -> request', request);
return next.handle(request).pipe(catchError(error => {
if (error instanceof HttpErrorResponse && error.status === 401) {
return this.handle401Error(request, next);
} else {
return throwError(error);
}
}));
}
private addToken(request: HttpRequest<any>, token: string): HttpRequest<any> {
return request.clone({
setHeaders: {
'Authorization': `Bearer ${token}`
}
});
}
private handle401Error(request: HttpRequest<any>, next: HttpHandler) {
if (!this.isRefreshing) {
this.isRefreshing = true;
this.refreshTokenSubject.next(null);
const tokenInfo = this.localstorage.getItem(AUTH_KEY);
return this.authService.authRefreshtokenPost({ refreshToken: tokenInfo.refreshToken }).pipe(
switchMap((tokenRes: any) => {
this.isRefreshing = false;
this.refreshTokenSubject.next(tokenRes.token);
this.localstorage.setItem(AUTH_KEY,
{ token: tokenRes.token, refreshToken: tokenRes.refreshToken, isAuthenticated: true });
return next.handle(this.addToken(request, tokenRes.token));
}), catchError((error) => {
console.log('TCL: JwtInterceptor -> privatehandle401Error -> error', error);
this.store.dispatch(new AuthActions.Logout({ refreshToken: tokenInfo.refreshToken }));
return next.handle(request);
}));
} else {
return this.refreshTokenSubject.pipe(
filter(token => token != null),
take(1),
switchMap(jwt => {
return next.handle(this.addToken(request, jwt));
}));
}
}
}
Lazy load module
#NgModule({
imports: [
ThemeModule,
PetsRoutingModule,
StoreModule.forFeature("pets", petsReducer),
TranslateModule.forChild({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
},
isolate: true
}),
EffectsModule.forFeature([PetsEffects]),
InfiniteScrollModule,
SharedModule
],
declarations: [
PetsComponent,
CreatePetComponent,
ViewPetComponent,
FormPetComponent,
EditPetComponent,
PetListVirtualComponent
],
providers: []
})
export class PetsModule {}
If I export my 2 interceptors in petsModule its intercept the request but I want to import it once only in core module. I checkout this stackblitz https://stackblitz.com/edit/angular-http-interceptor-working-for-lazy-loaded-module?file=src/app/core/token-interceptor.service.ts and I ensure that I only import HttpClientModule in my core module.
For use interceptor globally and the providers are in core module should add #Injectable({
providedIn: 'root'
}) in the top of interceptors like here
https://stackblitz.com/edit/angular-http-interceptor-working-for-lazy-loaded-module?file=src/app/core/token-interceptor.service.ts