Robert Daraż
Robert Daraż

Reputation: 323

Service don't return data from json by using BehaviorSubject

I have a JSON data as below:

import { Person } from './models';

export const People = [
  {
    name: 'Kimberly',
    lastname: 'Garcia',
    age: 26,
    sex: 'F',
  },
  {
    name: 'Chris',
    lastname: 'Williams',
    age: 64,
    sex: 'M',
  },
] as Person[];

I have a service which who emit data during ngOnInit hook like below:

import { Injectable } from "@angular/core";
import { BehaviorSubject, Observable } from "rxjs";
import { People } from "./data.json";
import { Person } from "./models";

@Injectable()
export class AppService {
  people$: Observable<Person[]>;
  private _people$: BehaviorSubject<Person[]>;

  constructor() {}

  ngOnInit() {
    this.setPeople();
  }

  getPeople() {
    //Get People list as observable. Please use BehaviorSubject for that.
    this.people$ = this._people$.asObservable();
  }

  setPeople() {
    this._people$.next(People);
  }
}

I am reading data into the component observable:

import { Component } from "@angular/core";
import { Observable } from "rxjs";
import { AppService } from "./app.service";
import { Person } from "./models";

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.scss"],
})
export class AppComponent {
  title = "interview";
  people$: Observable<Person[]>;

  constructor(private service: AppService) {}

  ngOnInit() {
    this.people$ = this.service.people$;
  }
}

I'm presenting data in the template:

<h1>{{ title }}</h1>
<ul>
  <li *ngFor="let person of people$ | async">
    {{ person.name }}
  </li>
</ul>

I don't get it why I cannot see any data from JSON. I'm adding them to the BehaviorSubject in ngOnInit hook. What's wrong? I also don't see any bugs in console of browser. I couldn't find solution - I have to use BehaviorSubject.

Upvotes: 0

Views: 255

Answers (1)

Alexander Staroselsky
Alexander Staroselsky

Reputation: 38807

Try updating _people$ to create an instance of a BehaviorSubject using new:

import { Injectable } from "@angular/core";
import { BehaviorSubject, Observable } from "rxjs";
import { People } from "./data.json";
import { Person } from "./models";

@Injectable()
export class AppService {
  // initialize with empty array for ngFor safety
  private _people$: BehaviorSubject<Person[]> = new BehaviorSubject<Person[]>([]);
  // this can still be in getPeople if you prefer
  people$: Observable<Person[]> = this._people$.asObservable();

  constructor() {
     this.setPeople();
  }

  setPeople() {
    this._people$.next(People);
  }
}

A couple other issues in your component when you set this.people$, the value of this.service.people$ is effectively undefined/null because getPeople() has not been called first. You can avoid that by updating getPeople() to return the actual observable people$ of the service, or simply setting people$ right after you instantiate the behavior subject like people$: Observable<Person[]> = this._people$.asObservable();.

Upvotes: 1

Related Questions