2

For my app, I need to use List.json to consctruct a list (the core of my app). To share this list between all my components, I've decided to create a service.

In this service, I call my json file in the constructor, and use a getter to get this list in others components. But when I call the getter, the constructor has not finished (http get is a little bit slow) and it returns nothing.. (with a little timeout, everyting works fine but it's dirty)

Is it possible to call the getter once the constructor is finished ?

Thanks in advance !

My service:

import {Injectable} from "angular2/core";
import {Http, Response, HTTP_PROVIDERS} from 'angular2/http';

@Injectable()
export class listService {
    private list;


    constructor(http: Http) {
        http.get('app/List.json')
            .map(res => res.json())
            .subscribe(
              data => this.list = data 
            );
    }


    getValue(){
        return this.list;
    }
}

My component which display the list:

import {listService} from './listService';
import {Component} from 'angular2/core';
import {RouteConfig, ROUTER_DIRECTIVES, Router} from 'angular2/router';
import 'rxjs/add/operator/map';

@Component({
  selector: 'list',
  template: `
    <h2>Formations </h2>
    <ul><li (click)='showItem(item)'  *ngFor="#item of list"><span >{{item.Method}}</span></li></ul>
`,
  directives: [ROUTER_DIRECTIVES]
})
export class List {
  public list: Object[];
  constructor(private listService:listService, private _router: Router) {
      this.list = this.listService.getValue();
  }
  showItem(item){
    this._router.navigate( ['Item', { id: item.id }] );
  }  
}
Gen
  • 31
  • 1
  • 5

3 Answers3

1
constructor(private http: Http) {
}     
getValue(){
        return this.http.get('app/LSD.json')
            .map(res => res.json());
}

export class List {
  public list: Object[];
  constructor(private listService:listService, private _router: Router) {
       this.listService.getValue().subscribe(
              data => this.list = data 
            );
  }

}
micronyks
  • 54,797
  • 15
  • 112
  • 146
  • Thanks for your answer but with your code I'll use a request each time I call the getter.. – Gen Mar 31 '16 at 12:31
0

You could leverage an observable as return of your getValue method. This way, components will be notified with the value.

@Injectable()
export class listService {
  private list;
  private obs;

  constructor(http: Http) {
    this.obs = http.get('app/List.json')
        .map(res => res.json())
        .do(
          data => {
            this.list = data;
        ).share();
  }

  getValue() {
    if (this.list) {
      return Observable.of(this.list);
    } else {
      return this.obs;
    }
  }
}

Update

In your component, you need to register on the returned observable:

@Component({
})
export class SomeComponent {
  constructor(private service: listService) {
    this.service.getValue().subscribe(
      (list) => {
        // do something with the list
      });
  }
}
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • Thanks for this example ! But share() seems to be undefined and how should I use the return of getValue() in my component ? Many thanks – Gen Apr 01 '16 at 08:39
  • You're welcome! By default all observable operators aren't included. You could try to import the following: `import 'rxjs/Rx`. See this question for more details: http://stackoverflow.com/questions/34515173/angular-2-http-get-with-typescript-error-http-get-map-is-not-a-function-in/34515276#34515276 – Thierry Templier Apr 01 '16 at 08:43
  • Again thanks for this quick answer ! I think I'm doing something wrong, I import `import 'rxjs/Rx'` and in my index `` but I still have the undefined error – Gen Apr 01 '16 at 09:19
  • Seems good! Oh there was a typo in one of my snippet. The `do` operator must be used in the service instead of subscribing. It should be better now. Sorry! – Thierry Templier Apr 01 '16 at 09:22
0

Using the approach from https://stackoverflow.com/a/36296015/217408

It stores an observable that is returned by getValue(). The observable is built in a way that multiple subscribers get the same value.

There is no way to directly get the value of async calls like http.get()

import {Injectable} from "angular2/core";
import {Http, Response, HTTP_PROVIDERS} from 'angular2/http';

@Injectable()
export class listService {
    private list;


    constructor(http: Http) {
        this.observable = this.http.get('app/List.json')
            .map(res => res.json()).publishLast().refCount();

    }


    getValue(){
        return this.observable;
    }
}
import {listService} from './listService';
import {Component} from 'angular2/core';
import {RouteConfig, ROUTER_DIRECTIVES, Router} from 'angular2/router';
import 'rxjs/add/operator/map';

@Component({
  selector: 'list',
  template: `
    <h2>Formations </h2>
    <ul><li (click)='showItem(item)'  *ngFor="#item of list"><span >{{item.Method}}</span></li></ul>
`,
  directives: [ROUTER_DIRECTIVES]
})
export class List {
  public list: Object[];
  constructor(private listService:listService, private _router: Router) {
      this.listService.getValue().subscribe(value => this.list = value);
  }
  showItem(item){
    this._router.navigate( ['Item', { id: item.id }] );
  }  
}
Community
  • 1
  • 1
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567