Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

361
Views
problem with angular subscribing an observable

I'm trying to make a service that gets a post from a json file containing array of posts. i have already a service that returns a json file contents by using HttpClient. the goal is to show the full post contents.

the service that gets a json file:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class GetJsonFileService {

  constructor(private http: HttpClient) {}

  getJsonFile(jsonFile: string /* the file path is set by components */){
    return this.http.get(jsonFile,{observe: 'body', responseType: 'json'});
  }
}

the service that gets a post by its id:

import { Injectable } from '@angular/core';
import { GetJsonFileService } from './get-json-file.service';

@Injectable({
  providedIn: 'root'
})
export class GetPostService {

  constructor(private getJsonFileservice: GetJsonFileService) {}

  getPost(id: number) :object{
    var post!: object;
    this.getJsonFileservice.getJsonFile('assets/posts.json').subscribe((data :any)=>{
      post = data["posts"][id];
    });
    return post;
  }

}

the component that shows the post:

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { GetPostService } from '../services/get-post.service';

@Component({
  selector: 'app-post-view',
  templateUrl: './post-view.component.html',
  styleUrls: ['./post-view.component.scss']
})
export class PostViewComponent implements OnInit {

  _post!: object;
  id!: number;

  constructor(private route: ActivatedRoute, private getPost: GetPostService){}

  ngOnInit(){
    var id!: number;
    this.route.params.subscribe(params=>{
      id = params.id;
    });
    this._post = this.getPost.getPost(id);
  }
}

when i try to show something in the component template like: {{_post.title}}

i get this error: Errors while compiling. Reload prevented.

and in vscode typescript tells me this: Property 'title' does not exist on type 'object'

I Tried @msanford's solution. there still one thing to change in post-view but i don't really know how to do it: posts["posts"][id] typescript gives me an error:

Element implicitly has an 'any' type because expression of type '"posts"' can't be used to index type 'Object'.
  Property 'posts' does not exist on type 'Object'

any ideas?

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

You have declared your post to be of type object: _post!: object; and, well, Property 'title' does not exist on type 'object'.

You should declare an interface or class with the fields of what a post actually contains. Just as an example:

interface Post {
  id: number;
  title: string;
  body: string;
  author: string;
  // etc
}

And use that in your type declaration: _post: Post;

That said, as others have pointed out, your service and component logic needs work.

You don't typically .subscribe() in a service, but in the consumer of the service, which is the component. So, instead of

// Service
getPost(id: number) :object{
    var post!: object;
    this.getJsonFileservice.getJsonFile('assets/posts.json').subscribe((data :any)=>{
      post = data["posts"][id];
    });
    return post;
  }

Use simply

// Service
getPost = (): Post  => this.getJsonFileservice.getJsonFile<Post[]>('assets/posts.json')

(Edit: I've cast your service return above in the customary way by adding <Post[]> to the call, but since I have not yet seen your data structure, it may require something different.)

And then Subscribe in your Component

ngOnInit(){
    let id: number;

    this.route.params.subscribe(
        params => id = params.id,
        error => console.error,
        complete => {
          this.getPost.getPost().subscribe(
            posts => this._post = posts["posts"][id],
            error => console.error
          );
        }
    );    
  }

where you also had a race condition where you could have asked for a post before the router sent you params with the id, which is presumably why you added the non-null-assertion operator id !: number because the compiler told you it might be null. There was a reason for that, don't override it.

over 4 years ago · Santiago Trujillo Report

0

You have a problem that you are returning the post before it is assigned:

post = data["posts"][id];

The best way is to return an observable and subscribe to it whenever you want the value provided.

Make sure to read the Documentation carefully to understand how observables work.

https://angular.io/guide/observables

over 4 years ago · Santiago Trujillo Report

0

Since Angular is using Typescript, you'll have to either mark _post as any or create a typescript interface/type for it with the fields you're expecting to have.

Oh you can also do this:

export class PostViewComponent implements OnInit {

  _post!: {
      title: string
  };
  id!: number;

  constructor(private route: ActivatedRoute, private getPost: GetPostService){}

  ngOnInit(){
    var id!: number;
    this.route.params.subscribe(params=>{
      id = params.id;
    });
    this._post = this.getPost.getPost(id);
  }
}
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!