Explicación: Servicios http
Completion requirements
6. GET por ID con routing
6.5. Página DETALLE (ActivatedRoute + GET by id)
src/app/pages/post-detail/post-detail.ts
import { Component } from '@angular/core';
import { ActivatedRoute, RouterLink } from '@angular/router';
import { Observable, switchMap } from 'rxjs';
import { PostsService } from '../../services/posts';
import { Post } from '../../models/post';
import { AsyncPipe } from '@angular/common';
@Component({
selector: 'app-post-detail',
imports: [RouterLink, AsyncPipe],
templateUrl: './post-detail.html',
styleUrl: './post-detail.css',
})
export class PostDetailComponent {
// 1) Escucho cambios en la URL
// 2) saco el id
// 3) hago getById(id)
post$!: Observable<Post>;
constructor(
private route: ActivatedRoute,
private postsService: PostsService
) {
this.post$ = this.route.paramMap.pipe(
switchMap(params => {
const id = Number(params.get('id'));
return this.postsService.getById(id);
})
);
}
}
post-detail.component.html
<a routerLink="/posts" class="link">← Volver</a>
@if (post$ | async; as p) {
<section class="box">
<h2>{{ p.title }}</h2>
<p>{{ p.body }}</p>
<p class="meta">
<b>ID:</b> {{ p.id }} · <b>User:</b> {{ p.userId }}
</p>
</section>
} @else {
<p>Cargando post...</p>
}
rc/app/pages/post-detail/post-detail.component.css
.link {
text-decoration: none;
border-bottom: 1px dotted #888;
}
.box {
border: 1px solid #eee;
border-radius: 12px;
padding: 14px;
background: #fff;
margin-top: 12px;
}
.meta {
opacity: 0.8;
margin-top: 10px;
}