angular2 translate ionic 2 No provider for Http! (MyApp -> TranslateService -> Http) - javascript

I am using ionic2/angular2 and ng2-translate. I get an error of "No provider for Http! (MyApp -> TranslateService -> Http)". I am not using typescript. I believe that this code is in typescript form. can someone help me convert it to javascript. Because i am using javascript for my ionic2 project. here is the code from the documentation of ng2-translate. I am just new to ionic2 and angular2.
import {provide} from '#angular/core';
import {TranslateService, TranslateLoader, TranslateStaticLoader} from 'ng2-translate/ng2-translate';
#App({
templateUrl: '....',
config: {},
providers: [
provide(TranslateLoader, {
useFactory: (http: Http) => new TranslateStaticLoader(http, 'assets/i18n', '.json'),
deps: [Http]
}),
TranslateService
]
})
here is my app.js
import {App, IonicApp, Platform, Storage, SqlStorage} from 'ionic-angular';
import {StatusBar} from 'ionic-native';
import {MainPage} from './pages/main/main';
import {TabsPage} from './pages/jeepney/tabs/tabs';
import {LandingPage} from './pages/landingpage/landingpage';
// import {JeepneyRoutesPage} from './pages/jeepney/jeep-routes/jeep-routes';
// import {ListPage} from './pages/list/list';
import {DataService} from './services/data';
import {ConnectivityService} from './providers/connectivity-service/connectivity-service';
import {GoogleMapsService} from './providers/google-maps-service/google-maps-service';
import {LoadingModal} from './components/loading-modal/loading-modal';
import {provide} from 'angular2/core';
import {Http, HTTP_PROVIDERS} from 'angular2/http';
import {TranslateService, TranslateLoader, TranslateStaticLoader} from 'ng2-translate/ng2-translate';
#App({
templateUrl: 'build/app.html',
providers: [DataService,ConnectivityService,
HTTP_PROVIDERS,
provide(TranslateLoader, {
useFactory: (http: Http) => new TranslateStaticLoader(http, 'assets/i18n', '.json'),
deps: [Http]
}),
TranslateService],
directives: [LoadingModal],
config: {
iconMode: 'md',
modalEnter: 'modal-slide-in',
modalLeave: 'modal-slide-out',
pageTransition: 'ios',
tabSubPages: false,
backButtonIcon: 'ios-arrow-back',
tabbarPlacement: 'top',
backButtonText: ''
// menuType: 'reveal'
} // http://ionicframework.com/docs/v2/api/config/Config/
})
class MyApp {
static get parameters() {
return [[IonicApp], [Platform],[TranslateService]];
}
constructor(app, platform,translate) {
this.translate=translate;
// set up our app
this.app = app;
this.platform = platform;
this.initializeApp();
// make HelloIonicPage the root (or first) page
this.rootPage = LandingPage;
// this.initializeTranslateServiceConfig();
var userLang = navigator.language.split('-')[0]; // use navigator lang if available
userLang = /(fr|en)/gi.test(userLang) ? userLang : 'en';
// this language will be used as a fallback when a translation isn't found in the current language
this.translate.setDefaultLang('en');
// the lang to use, if the lang isn't available, it will use the current loader to get them
this.translate.use(userLang);
}
initializeTranslateServiceConfig() {
var prefix = 'assets/i18n/';
var suffix = '.json';
this.translate.useStaticFilesLoader(prefix, suffix);
var userLang = navigator.language.split('-')[0];
userLang = /(de|en|hr)/gi.test(userLang) ? userLang : 'en';
this.translate.setDefaultLang('en');
this.translate.use(userLang);
}
initializeApp() {
this.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();
// this.storage = new Storage(SqlStorage);
// this.storage.query('CREATE TABLE IF NOT EXISTS people (id INTEGER PRIMARY KEY AUTOINCREMENT, firstname TEXT, lastname TEXT)').then((data) => {
// console.log("TABLE CREATED -> " + JSON.stringify(data.res));
// }, (error) => {
// console.log("ERROR -> " + JSON.stringify(error.err));
// });
});
}
}

You need to provide HTTP_PROVIDERS:
import {HTTP_PROVIDERS, Http} from '#angular/http';
#App({
templateUrl: '....',
config: {},
providers: [
HTTP_PROVIDERS,
provide(TranslateLoader, {
useFactory: (http: Http) => new TranslateStaticLoader(http, 'assets/i18n', '.json'),
deps: [Http]
}),
TranslateService
]
})

this is how it worked out for me.
check out the app.module.ts file
import { NgModule, ErrorHandler } from '#angular/core';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import { TranslateModule, TranslateStaticLoader, TranslateLoader } from 'ng2-translate/ng2-translate';
import { Http } from '#angular/http'
export function createTranslateLoader(http: Http) {
return new TranslateStaticLoader(http, 'assets/i18n', '.json');
}
#NgModule({
declarations: [
MyApp,
HomePage
],
imports: [
IonicModule.forRoot(MyApp),
TranslateModule.forRoot({
provide: TranslateLoader,
useFactory: (createTranslateLoader),
deps: [Http]
})
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
HomePage
],
providers: [{provide: ErrorHandler, useClass: IonicErrorHandler}]
})
export class AppModule {}
you can find a complete repo here:
https://github.com/philipphalder/ionic2-rc3-NG2-Translate

Related

How do I Access AppModule Module imports from Lazy-loaded Modules?

How do I Access AppModule imports from Lazy-loaded Modules ?
My Angular10 App imports AngularMaterial and NXTranslate Modules in to the AppModule.
NxTranslate calls an ApiService to get a large Lookup object of thousands of translations.
This is translated at the initial loading of the AppModule.
The App has multiple lazy-loaded routes that also need to use the AnagularMaterial and NXTranslate Modules in their features.
If I use a SharedModule to load the Modules then the ApiService is called multiple times. This is obviously not good.
It should only call the ApiService & AngularMaterial once and be available for all modules.
How do I resolve this? I am struggling.
Thanks.
Update
(sorry for the long post)
This is the NXTranslate implementation - it uses a custom class.
import { environment } from './../../../../environments/environment';
import { OSCITranslateService } from './translate.service';
import { NgModule, Injector } from '#angular/core';
import { CommonModule } from '#angular/common';
import {TranslateLoader, TranslateModule} from '#ngx-translate/core';
import {TranslateHttpLoader} from '#ngx-translate/http-loader';
import {HttpClient, HttpClientModule} from '#angular/common/http';
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
export class CustomLoader implements TranslateLoader {
localeResourcesUrl =
`${environment.baseUrl}${environment.apiUrl.localeResources}`;
constructor(private http: HttpClient) {}
getTranslation(lang: string): Observable<any> {
let options;
const uri = `${this.localeResourcesUrl}${options && options.key ?
'/' + options.key : ''}`;
let mapped = this.http.get(uri).pipe(
map((response: any) => {
let localeData = {};
let languageCode = response?.languageVariantCode;
response.resources.forEach(item => {
localeData[item.keyName] = item.keyValue;
});
return localeData;
})
);
return mapped;
}
}
#NgModule({
declarations: [],
imports: [
CommonModule,
HttpClientModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useClass: CustomLoader,
deps: [HttpClient]
}
})
],
exports: [ TranslateModule ]
})
export class NxTranslateModule {
constructor(private http: HttpClient) {
}
}
This is the sharedRootModule that imports the AngularMaterial & NXTranslate
import { SharedModule } from './shared.module';
import { NgModule, ModuleWithProviders } from '#angular/core';
#NgModule({
})
export class SharedRootModule {
static forRoot(): ModuleWithProviders<SharedModule> {
return {
ngModule: SharedModule
};
}
}
In AppModule SharedRootModule is imported
...
#NgModule({
declarations: [
AppComponent
],
imports: [
...
SharedRootModule.forRoot()
],
exports: [
...
SharedRootModule
]
....
Are you concerned about the multiple ApiService instances you might end up with? Provide the ApiService within AppModule only, or even better, use the providedIn property right in your service's decorator so it gets injected at application level. (https://angular.io/api/core/Injectable#providedIn)
I would just use a SharedModule that exports the mentioned lazy loaded modules.

ngx-cookie - blank cookie object in server side rendering

I have a angular application in which angular universal is enabled and i am rendering data from API but that includes the work of cookies. I make API call after checking a value in user browser cookies.
But for Angular SSR(server side rendering) there is no cookie and i am getting {} blank object when trying to use this console.log(this.cookie.getAll());.
I am using ngx-cookie package and my installation is this
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { SlickCarouselModule } from 'ngx-slick-carousel';
import { SharedModule } from './shared/shared.module';
import { CookieModule } from 'ngx-cookie';
import { HttpClientModule } from '#angular/common/http';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { CommonModule } from '#angular/common';
import { TransferHttpCacheModule } from '#nguniversal/common';
import { NgtUniversalModule } from '#ng-toolkit/universal';
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule.withServerTransition({ appId: 'serverApp' }),
CookieModule.forRoot(),
AppRoutingModule,
HttpClientModule,
CommonModule,
TransferHttpCacheModule,
NgtUniversalModule,
SlickCarouselModule,
SharedModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
app.server.module.ts
import { NgModule } from '#angular/core';
import { ServerModule, ServerTransferStateModule } from '#angular/platform-server';
import { CookieService, CookieBackendService } from 'ngx-cookie';
import { AppModule } from './app.module';
import { AppComponent } from './app.component';
import { ModuleMapLoaderModule } from '#nguniversal/module-map-ngfactory-loader';
import { SharedModule } from './shared/shared.module';
#NgModule({
imports: [
AppModule,
ServerModule,
ModuleMapLoaderModule,
ServerTransferStateModule,
SharedModule
],
bootstrap: [AppComponent],
providers: [{ provide: CookieService, useClass: CookieBackendService }]
})
export class AppServerModule {}
server.ts
I have applied this
app.get('*', (req, res) => {
res.render('index', {
req: req,
res: res,
providers: [
{
provide: 'REQUEST', useValue: (req)
},
{
provide: 'RESPONSE', useValue: (res)
}
]
});
});
Still i can only access cookies in browser but not server side.
Any help would be appreciated.
You can send cookies with every request to server using Interceptor
Here is an example how to use it:
intercreptor.service.ts
import { Injectable } from '#angular/core';
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '#angular/common/http';
import { Observable } from 'rxjs';
import { CookieService } from 'ngx-cookie';
#Injectable()
export class InterceptorService implements HttpInterceptor {
constructor(private cookies: CookieService) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let token = this.cookies.get("my-access-token");
if(token) req = req.clone({
setHeaders: { Authorization: `Bearer ${token}`}
});
return next.handle(req)
}
}
intercreptor.module.ts
import { NgModule } from '#angular/core';
import { HttpClientModule, HTTP_INTERCEPTORS } from '#angular/common/http';
import { InterceptorService } from './interceptors/authorization';
#NgModule({
imports: [
HttpClientModule
],
providers: [{
provide: HTTP_INTERCEPTORS,
useClass: InterceptorService,
multi: true
}]
})
export class InterceptorModule { }
and import InterceptorModule into your app.module.ts

use AngularJS service for Angular component

I have AngularJS service :
var id = 'authService';
angular.module('app')
.service(id, ['$http', '$q', '$injector', 'storageSvc', 'notifyHub', 'sysSettings', '$rootScope', 'crudSvc', authService]);
and would like to use it inside my angular component SignInComponent :
import { Component, Inject } from '#angular/core';
import { Account } from '../../../../shared/models/account';
import { AuthService } from "../../../../shared/angularJS-upgraded-providers";
#Component({
selector: 'sign-in',
templateUrl: './sign-in.component.html'
})
export class SignInComponent {
constructor(
#Inject(AuthService) private authService: any) {
this.authService = authService;
}
model = new Account('admin02', 'Admin#002', true);
onLogin() {
this.authService.login(this.model).then(response => {
if (response != null) {
alert("Seems it works");
}
});
}
}
For this purpose I created angularJS-upgraded-providers.ts file :
import { InjectionToken } from "#angular/core";
export const AuthService = new InjectionToken<any>('authService');
export function authServiceFactory(i: any) {
return i.get('authService');
}
export const authServiceProvider = {
provide: AuthService,
useFactory: authServiceFactory,
deps: ['$injector']
};
and trying to reuse it inside app.module.ts :
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { UpgradeModule } from '#angular/upgrade/static';
import { SignInComponent } from "./modules/login/components/sign-in/sign-in.component";
import { authServiceProvider } from './shared/angularJS-upgraded-providers';
#NgModule({
declarations: [
SignInComponent
],
imports: [
BrowserModule,
UpgradeModule,
FormsModule
],
entryComponents: [
SignInComponent
],
providers: [authServiceProvider
],
bootstrap: [SignInComponent]
})
export class AppModule {
constructor(private upgrade: UpgradeModule) { }
ngOnInit() {
this.upgrade.bootstrap(document.body, ['app']);
}
}
My start file - main.ts looks like this :
import { enableProdMode } from '#angular/core';
import { platformBrowserDynamic } from '#angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule);
But when I am trying to run my program I have an error :
ERROR Error: Trying to get the AngularJS injector before it being set.
at injectorFactory (static.js:690)
at _callFactory (core.js:10956)
at _createProviderInstance$1 (core.js:10910)
at resolveNgModuleDep (core.js:10892)
at _callFactory (core.js:10958)
at _createProviderInstance$1 (core.js:10910)
at resolveNgModuleDep (core.js:10892)
at NgModuleRef_.push../node_modules/#angular/core/esm5/core.js.NgModuleRef_.get (core.js:12129)
at resolveDep (core.js:12619)
at createClass (core.js:12481)
Could please anybody provide algorithm or at least give an idea what i am doing wrong and why i am getting the error : Error: Trying to get the AngularJS injector before it being set?
Which template or pattern I could use to be able to consume AngularJS service inside my Angular5 app?
AngularJS version : 1.6.8,
Angular version : 5.2.11
Thank you for your time

Angular 5 Provide http interceptor based on environment

I have the following two environments in my angular-cli (v1.5.1, angular v5) application:
dev
prod
Dev makes use of mock data, which I provide with an http-interceptor.
Pro makes use of a live rest api.
How do I provide the http-interceptor on dev, but not on pro?
I already tried the following, but it doesn't work:
{
provide: HTTP_INTERCEPTORS,
useFactory: () => {
if (environment.useMockBackend === true) {
return MockHttpInterceptor;
}
return false;
},
multi: true
}
In my Angular 5.2 project I used following approach.
app.module.ts
import { HttpClientModule, HTTP_INTERCEPTORS } from '#angular/common/http';
import { environment } from '../environments/environment';
import { MyInterceptor } from './my.interceptor';
const commonProviders = [/*...*/];
const nonProductionProviders = [{
provide: HTTP_INTERCEPTORS,
useClass: MyInterceptor,
multi: true
}];
#NgModule({
imports: [
HttpClientModule,
// ...
],
providers: [
...commonProviders,
...!environment.production ? nonProductionProviders : []
]
})
my.interceptor.ts
import { Injectable } from '#angular/core';
import { HttpEvent, HttpRequest, HttpInterceptor, HttpHandler } from '#angular/common/http';
import { Observable } from 'rxjs';
#Injectable()
export class MyInterceptor implements HttpInterceptor {
intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
// ...
return next.handle(req);
}
}
I've come up with the following approach (this is in Angular 7), by drawing on the previous answers from #dhilt and #kemsky:
Your dev environment file
import { HTTP_INTERCEPTORS } from '#angular/common/http';
import { MyDevInterceptor} from './my-dev.interceptor';
export const ENVIRONMENT_SPECIFIC_PROVIDERS = [
{ provide: HTTP_INTERCEPTORS, useClass: MyDevInterceptor, multi: true }
];
environment.prod.ts
export const ENVIRONMENT_SPECIFIC_PROVIDERS = [];
app.module.ts
#NgModule({
declarations: [],
imports: [
HttpClientModule
],
providers: [
ENVIRONMENT_SPECIFIC_PROVIDERS
]
})
It's simple, it works a treat, and it means that your code base contains no references to anything that's not required by your environment.
The idea is to export interceptor providers from environment file, prod environment exports do-nothing interceptor or just any other dummy provider (lets name it DefaultHttpInterceptor) and dev exports MockHttpInterceptor.
dev environment: export const INTERCEPTORS = {provide: HTTP_INTERCEPTORS, ... MockHttpInterceptor}
prod environment: export const INTERCEPTORS = {provide: HTTP_INTERCEPTORS, ... DefaultHttpInterceptor}
Then you can use it like usual:
import { INTERCEPTORS } from './../environments/environment';
#NgModule({
providers : [
...
INTERCEPTORS
...
]
...
})

Angular2 Loading the api configuration from the server side before the app bootstrap starts shows

I am using the angular 2 web app. In that, i am getting app configuration details from the api before the app bootsrap. For that i searched on the browser and find out these links
How to call an rest api while bootstrapping angular 2 app
https://gist.github.com/fernandohu/122e88c3bcd210bbe41c608c36306db9
And followed them. In the angular-cli and also on the browser console i didn't get any error. But my page comes empty with loading text, that was i displayed in the before loading angular.
Here is my code
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule, APP_INITIALIZER } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { HttpModule, Http} from '#angular/http';
import { SocketIoModule, SocketIoConfig } from 'ng2-socket-io';
import { SharedModule } from './shared/shared.module';
import { TranslateModule, TranslateLoader} from '#ngx-translate/core';
import { TranslateHttpLoader} from '#ngx-translate/http-loader';
import { AppRoutingModule } from './app.route';
import { AppComponent } from './app.component';
import { ChatComponent } from './chat/chat.component';
import { ChatService } from './chat/chat.service';
import { AddressComponent } from './address/address.component';
import { HomeComponent } from './home/home.component';
import { SettingService } from './shared/service/api/SettingService';
import { FilterByPipe } from './filterPipe';
import { Ng2ScrollableModule } from 'ng2-scrollable';
import { AppConfig } from './app.config';
import {Injectable} from '#angular/core';
import {Observable} from 'rxjs/Rx';
const config: SocketIoConfig = { url: 'http://192.168.1.113:7002', options: {} };
export function HttpLoaderFactory(http: Http) {
return new TranslateHttpLoader(http, "http://192.168.1.114:7001/frontend-translation/", "");
}
export function SettingServiceFactory(setting: SettingService) {
return () => setting.load();
//return true;
}
#NgModule({
declarations: [
AppComponent,
ChatComponent,
AddressComponent,
HomeComponent,
FilterByPipe
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
AppRoutingModule,
Ng2ScrollableModule,
SocketIoModule.forRoot(config),
SharedModule,
TranslateModule.forRoot({
loader: {
provide : TranslateLoader,
useFactory: HttpLoaderFactory,
deps : [Http]
}
}),
],
providers: [
ChatService,
AppConfig,
SettingService,
{
provide : APP_INITIALIZER,
useFactory: SettingServiceFactory,
deps : [SettingService],
multi : true
}
/*SettingService,
{
provide : APP_INITIALIZER,
useFactory: (setting:SettingService) => () => setting.load(),
//deps : SettingService,
multi : true
}*/
],
bootstrap: [AppComponent]
})
export class AppModule { }
SettingService.ts
In this file, i am loading the api configuration from the server side
import {Injectable} from '#angular/core';
import {Http, Response} from '#angular/http';
import {Observable} from 'rxjs/Rx';
#Injectable()
export class SettingService {
public setting;
constructor(private http: Http) {}
/**
* Retrieves the setting details of the website
* #return {Object} language tranlsation
*/
public load()
{
return new Promise((resolve, reject) => {
this.http
.get('http://192.168.1.114:7001/settings')
.map( res => res.json() )
.catch((error: any):any => {
console.log('Configuration file "env.json" could not be read');
resolve(true);
return Observable.throw(error.json().error || 'Server error');
})
.subscribe( (envResponse) => {
this.setting = envResponse;
});
});
}
}
When i replace the load() api service within below code it works fine
public load() {
return {
"test": "works well"
}
}
But with api call, it doesn't.
What i found was, when i am returning the json object it works, but when i am making api call return the promise object it won't. I don't know how to solve this.
Thanks in advance.
My project was little bigger, so i can't put in plunker
Try to use promise object like this:
load(): Promise<Object> {
var promise = this.http.get('./app.json').map(res => res.json()).toPromise();
promise.then(res=> this.label= res);
return promise;
}

Categories