Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

360
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda