Estoy tratando de crear un servicio que reciba una publicación de un archivo json que contiene una variedad de publicaciones. ya tengo un servicio que devuelve el contenido de un archivo json usando HttpClient . el objetivo es mostrar el contenido completo de la publicación.
el servicio que obtiene un archivo json:
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'}); } }el servicio que recibe una publicación por su 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; } }el componente que muestra la publicación:
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); } } cuando trato de mostrar algo en la plantilla del componente como: {{_post.title}}
me sale este error: Errors while compiling. Reload prevented.
y en vscode mecanografiado me dice esto: Property 'title' does not exist on type 'object'
Probé la solución de @msanford. Todavía hay una cosa que cambiar en la vista posterior, pero realmente no sé cómo hacerlo: las posts["posts"][id] mecanografiado me dan un 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'¿algunas ideas?
Ha declarado que su publicación es de tipo objeto: _post!: object; y, bueno, la propiedad 'título' no existe en el tipo ' objeto '.
Debe declarar una interfaz o clase con los campos de lo que realmente contiene una publicación . Solo como un ejemplo:
interface Post { id: number; title: string; body: string; author: string; // etc } Y úsalo en tu declaración de tipo: _post: Post;
Dicho esto, como han señalado otros, la lógica de su servicio y componente necesita trabajo.
Por lo general, no utiliza .subscribe() en un servicio, sino en el consumidor del servicio, que es el componente. Entonces, en lugar de
// Service getPost(id: number) :object{ var post!: object; this.getJsonFileservice.getJsonFile('assets/posts.json').subscribe((data :any)=>{ post = data["posts"][id]; }); return post; }Usar simplemente
// Service getPost = (): Post => this.getJsonFileservice.getJsonFile<Post[]>('assets/posts.json') (Editar: emití su retorno de servicio arriba de la manera habitual agregando <Post[]> a la llamada, pero como aún no he visto su estructura de datos, puede requerir algo diferente).
Y luego Suscríbete en tu Componente
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 ); } ); } donde también tenía una condición de carrera en la que podría haber pedido una publicación antes de que el enrutador le enviara parámetros con la identificación, lo que presumiblemente es la razón por la que agregó la identificación del operador de afirmación no nula id !: number porque el compilador le dijo que podría ser nulo. Había una razón para eso, no la anule.
Tiene un problema que está devolviendo el correo antes de que se le asigne:
post = data["posts"][id];La mejor manera es devolver un observable y suscribirse a él cuando desee el valor proporcionado.
Asegúrese de leer la Documentación detenidamente para comprender cómo funcionan los observables.
Dado que Angular usa Typescript, deberá marcar _post como any o crear una interfaz/tipo de TypeScript para él con los campos que espera tener.
Oh, también puedes hacer esto:
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); } }