Crea una cuenta o inicia sesión

¡Continúa aprendiendo sin ningún costo! Únete y comienza a potenciar tu carrera

Página de categorías

4/25
Recursos

Cuando construyes URLs en tu aplicación, éstas pueden poseer parámetros dinámicos, por lo general, IDs para identificar registros, para capturarlos y manipularlos posteriormente.

Capturando parámetros de URL

Veamos a continuación dos maneras de capturar estos parámetros, una síncrona y otra asíncrona.

Captura de parámetros síncronos

El mejor lugar para capturar parámetros de URL, sean síncronos o no, es utilizando los hooks de ciclo de vida de Angular, más concretamente ngOnInit().

1. Creando rutas

Comienza creando tus rutas que permitan ingresar parámetros dinámicos de la siguiente manera:

// app-routing.module.ts
const routes: Routes = [
  {
    path: 'catalogo',
    component: CatalogoComponent
  },
  {
    path: 'catalogo/:categoryId',
    component: CatalogoComponent
  },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Observa que ambas rutas apuntan al mismo componente, eso está bien. La diferencia estará en que la segunda ruta posee :categoryId y podrás capturar el parámetro utilizando ese mismo nombre.

2. Inyección de servicios necesarios

En el componente correspondiente, inyecta el servicio ActivatedRoute y también importa Params para tipar tus datos y manipularlos más fácilmente. Ambos imports provenientes de @angular/router.

// modules/website/components/catalogo/catalogo.components.ts
import { ActivatedRoute, Params, Router } from '@angular/router';

@Component({
  selector: 'app-catalogo',
  templateUrl: './catalogo.component.html',
  styleUrls: ['./catalogo.component.scss']
})
export class CatalogoComponent {
  constructor(private route: ActivatedRoute) { }
}

3. Capturando parámetros

Es momento de capturar los parámetros en el ngOnInit(). Para esto, basta con una línea de código como la siguiente:

// modules/website/components/catalogo/catalogo.components.ts
ngOnInit(): void {
  const categoryId = this.route.snapshot.paramMap.get('categoryId');
  console.log(categoryId);
}

Guardarás en la constante categoryId el valor del parámetro que lleva el mismo nombre que definiste en el archivo app-routing.module.ts. Luego podrás utilizarlos para realizar peticiones a un servidor o para lo que necesites.

Captura de parámetros asíncronos

Una URL puede cambiar y a veces es conveniente estar escuchando de forma activa los cambios en la misma.
Para que los Observables nos ayuden a estar atentos a estos cambios, Angular también nos permite suscribirnos a los cambios en los parámetros de URL de la siguiente manera.

// modules/website/components/catalogo/catalogo.components.ts
ngOnInit(): void {
  this.route.paramMap
    .subscribe((params: Params) => {
      const categoryId = params.get('categoryId');
      console.log(categoryId);
    });
}

A través del nombre del parámetro definido en el archivo app-routing.module.ts, capturas los datos para manipularlos posteriormente.

De esta manera, puedes pasar parámetros dinámicamente, de forma síncrona o asíncrona, dependiendo tu necesidad y construir tu aplicación.


Contribución creada por: Kevin Fiorentino.

Aportes 8

Preguntas 6

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

creo estaría mejor si el profe escribe el código durante la clase, pasa que cuando copia y pega se mueve de archivos y por hacerlo rapido no explica claro lo que esta haciendo y es confuso

Aquí tenemos la url de la documentación de la API

A mi me estaba saliendo error al obtener el id con:

params.get('id')

lo que hice fue obtenerlo de esta forma:

this.categoryId = params['id'];

Para que les funcione para el 2023 tienen que modificar el archivo environment.ts:

export const environment = {
  production: false,
  API_URL: 'https://api.escuelajs.co/api/v1',
};

quedaria asi para las categories:

return this.http.get<Product[]>(`${this.apiUrl}/categories/${categoryId}/products`, { params })

hay que hacer ciertas modificacioens en las demas rutas, pero se puede usar el swagger UI como guia

Estoy lista

Buenas a todos, yo me desvié un poco de la línea que mantenía el profe y creé una paginación al estilo de page up page down, entonces para ello, en estos momentos mi código es algo diferente, pero lo más asombroso es que funciona para products en el home y en categories os dejo un avance aquí y un enlace al repo.

// category.component.ts
onPageUp(){
    if (this.limit * (this.page + 1) < this.MAX_PRODUCTS_IN_BD ) {
      this.page += 1;
      this.offset = this.limit * this.page;
      this.productsService.getProductsByPage(this.limit, this.offset)
        .subscribe(data => {
          this.products = data;
      });
    }
  }
// category.component.html
<app-products [products]="products" [page]="page" (pageUp)="onPageUp()" (pageDown)="onPageDown()"></app-products>
// products.componet.ts
@Input() products: Product[] = [];
  @Input() page=0;

  @Output() pageUp = new EventEmitter();
  @Output() pageDown = new EventEmitter();
 // ...
  onPageUp(){
    this.pageUp.emit();
  }
  onPageDown(){
    this.pageDown.emit();
  }

ver todo el código en este repo de github

repositorio

Solucion del reto

loadMore(): void {
    this.route.paramMap.subscribe((params) => {
      this.categoryId = params.get('id');
      if (this.categoryId) {
        this.productsService
          .getByCategory(this.categoryId, this.limit, this.offset)
          .subscribe((data) => {
            this.products = this.products.concat(
              data.filter((product) => product.images.length > 0)
            );
            this.offset += this.limit;
          });
      }
    });
  }

Lo que hice en este caso es manejar un router a un home despues de que haga login, esto validado con Guards.

Y ya lo que hice fue manejar todas las peticiones desde el products, aunque no se si es buena practica siento que es mas ordenado la manera que lo hace el profe. Pero les comparto el codigo.

Esto sin nada de inputs ni nada de logica en el home.

products.ts component

constructor(
    private storeServices: StoreService,
    private productService: ProductsService,
    private filesService: FilesService,
    private activatedRoute: ActivatedRoute
  ) {
    this.myShoppingCart = this.storeServices.getShopingCart()

  }

  ngOnInit(): void {
    this.activatedRoute.params.subscribe(params => {
      this.categoryId = params['id'];
      if (this.categoryId) {
        this.loadCategoryProducts(this.categoryId)
      }
    });
    this.loadProducts()
  }

  loadCategoryProducts(categoryId: string) {
    this.categoryId = categoryId;
    this.products = [];
    this.offset = 0;
    this.loadProducts();
  }

  loadProducts() {
    const request$ = this.categoryId ?
      this.productService.getCategory(this.categoryId, this.limit, this.offset) :
      this.productService.getAllProducts(this.limit, this.offset)

    request$
      .subscribe({
        next: (data: Product[]) => {
          this.products = this.products.concat(data);
          this.offset += this.limit;
          if (data.length === 0) {
            this.offset = 0;
          }
        },
        error: (error: string) => {
          this.loadingProducts = false
          Swal.fire({
            title: 'Error!',
            text: error,
            icon: 'error',
            confirmButtonText: 'Ok',
          });
        },
      });
  }

  loadMoreProducts() {
    this.offset += this.limit;
    this.loadProducts();
  }