4

I have a pipe that resolves message key and returns message accordingly to locale.

But i want angular to wait untill my service will finish it's loading messages, and only after that continue rendering the main page. Where my localization pipe is used. How to get it work?

Service:

@Injectable()
export class I18nService implements OnInit {

    private cachedMessages: {string: string};

    activeLocale:I18Enum = null;

    constructor(private http: Http) {
        this.reloadLocale(I18Enum.ru);
    }

    ngOnInit(): void {
        this.reloadLocale(I18Enum.ru);
    }

    getMessage(key: string) {
        if (this.cachedMessages) {
            return this.cachedMessages[key];
        }
    }

    reloadLocale(locale: I18Enum) {
        this.activeLocale = locale;
        this.http.get(basePath + i18nPath + I18Enum[locale]).subscribe(
            res => {
                this.cachedMessages = res.json();
            }
        );
    }
}

And pipe:

@Pipe({name: 'i18nPipe'})
export class I18nPipe implements PipeTransform {

    constructor(private i18Service: I18nService) {
    }

    transform(value: any, args: any): any {
        return this.i18Service.getMessage(value);
    }

}
Simon
  • 997
  • 1
  • 15
  • 29
  • 1
    Possible duplicate of [How to pass parameters rendered from backend to angular2 bootstrap method](http://stackoverflow.com/questions/37611549/how-to-pass-parameters-rendered-from-backend-to-angular2-bootstrap-method) – Estus Flask Nov 14 '16 at 14:36

1 Answers1

3

Ok. Finally i made it work. I found this answer and it helped me. https://stackoverflow.com/a/40379803/5203127

So my code now looks as below:

Service: (was added an initMessages method)

@Injectable()
export class I18nService {

    private cachedMessages: {string: string} = null;

    activeLocale: I18Enum = null;

    constructor(private http: Http) {

    }

    getMessage(key: string) {
        if (this.cachedMessages) {
            return this.cachedMessages[key];
        }
    }

    reloadLocale(locale: I18Enum) {
        this.activeLocale = locale;
        this.http.get(basePath + i18nPath + I18Enum[locale]).subscribe(
            res => {
                this.cachedMessages = res.json();
            }
        );
    }

    initMessages(locale: I18Enum) {
        this.activeLocale = locale;

        return new Promise((resolve, reject) => {
            this.http.get(basePath + i18nPath + I18Enum[locale]).map(res => res.json()).catch((error: any): any => {
                reject(false);
                return Observable.throw(error.json().error || 'Server error');
            }).subscribe((callResult: {string: string}) => {
                this.cachedMessages = callResult;
                resolve(true);
            });

        });
    }
}

My bootstrap: (was added APP_INITIALIZER provider)

    @NgModule({
        imports: [..., HttpModule, ...],
        declarations: [...,
            I18nPipe
        ],
        bootstrap: [AppComponent],
        providers: [..., I18nService,
            {
                provide: APP_INITIALIZER,

            // useFactory: (i18NService: I18nService) => () => i18NService.initMessages(I18Enum.ru),
            // or
            useFactory: initApp,

            deps: [I18nService],
            multi: true
        }
    ]
})
export class TopJavaModule {

}

export function initApp(i18nService: I18nService){
    // Do initing of services that is required before app loads
    // NOTE: this factory needs to return a function (that then returns a promise)
    return () => i18nService.initMessages(I18Enum.ru);  // + any other services...
}
Community
  • 1
  • 1
Simon
  • 997
  • 1
  • 15
  • 29