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;
}