1

I'm currently teaching myself Angular2 and having a few teething problems (to say the least). Anyway, I wish to create a service that loads a static JSON file. For the time being I am using i18n files as they have structured JSON. The service will also have a method that will take a passed parameter (an argument) and will then look for the JSON property with the name of the passed parameter. Sounds pretty simple but I have a few questions, first off all here is my service I imaginally called ContentService, the file is content.service.ts

import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http'

@Injectable()
export class ContentService {

    loadedContent: any; // will create a real type later

    constructor(private http: Http) {

        // 1. Determine the language
        let userLang:string = navigator.language.split('-')[ 0 ];
        userLang = /(en|de)/gi.test(userLang) ? userLang : 'en';

        // 2. Load the file... I should really use interpolation for the file path
         this.http.get('src/i18n/' + userLang + '.json').map((res:Response) => res.json()).subscribe(res => this.loadedContent = res);
    }

    getContent(selector) {

        // in here we need to pass the selector and fetch the content from the loaded JSON, however for now I will just return the passed selector and see if I have access to the loadedConent
        console.log(selector, this.loadedContent); // this.loadedContent is undefined!
        // we need a catch for we the selector is not found....
    }
}

in another component I import the service...

import { ContentService } from '../content/content.service';

@Component({
    selector: 'angular2-test',
    providers: [ ContentService ],
    templateUrl: 'src/home/home.template.html'
})

export class TestComponent {

    content: any; // real type to come later

    constructor(private contentService: ContentService) {
        this.content = this.contentService.getContent('promotion')
    }
}

Now obviously I have a bit of an error as in my getContent method I have no access to this.loadedContent and in the console I am returning "underfined". How can I get my method to have access to the loadedContent property of my service?

BTW: this is the content of my static JSON file and it is loading in the service...

{
  "promotion": {
    "pageTitle": "Oh we have a lovely promotion today..."
  }
}

Thanks in advance!

Mike Sav
  • 14,805
  • 31
  • 98
  • 143

1 Answers1

3

I would rework your service to make it asynchronous:

import {Observable} from 'rxjs/Rx';

@Injectable()
export class ContentService {
  loadedContent: any; // will create a real type later
  obs: Observable<any>;

  constructor(private http: Http) {
    let userLang:string = navigator.language.split('-')[ 0 ];
    userLang = /(en|de)/gi.test(userLang) ? userLang : 'en';

    this.obs = this.http.get('src/i18n/' + userLang + '.json')
      .map((res:Response) => res.json())
      .do(res => this.loadedContent = res);
  }

  getContent(selector) {
    if (this.loadedContent) {
      return Observable.of(this.loadedContent);
    } else {
      return this.obs;
    }
  }
}

and use it this way in your component:

@Component({
  selector: 'angular2-test',
  providers: [ ContentService ],
  templateUrl: 'src/home/home.template.html'
})
export class TestComponent {
  content: any; // real type to come later

  constructor(private contentService: ContentService) {
    this.contentService.getContent('promotion').subscribe(content => {
      this.content = content;
    });
  }
}

Another option could also be to bootstrap your application asynchronously. See this question for more details:

Community
  • 1
  • 1
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • 2
    Thanks, however I assume I need to give this.obs a type too / declare it at the top of my service? I also need to import Observable from RxJS – Mike Sav May 24 '16 at 09:43
  • Great, thanks for the link too! I do get a warning about 'unresolved method or function of()' but I can live with that, now I can write the code to return the desired node (the actual JSON is much larger)! Thanks a lot! – Mike Sav May 24 '16 at 09:52
  • You're welcome ;-) Strange for the warning? Is it in your editor or when you compile your application with tsc? – Thierry Templier May 24 '16 at 09:54
  • I do have another question, is it possible to chat for a sec? – Mike Sav May 24 '16 at 09:57