No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Product Detail

3/20
Recursos

Aportes 1

Preguntas 0

Ordenar por:

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

Para ver el funcionamiento de product detail hay que tomar en cuenta que comienza desde el app-routing.model.ts

app-routing.model.ts

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { PicoPreviewComponent } from './components/pico-preview/pico-preview.component';
import { PeopleComponent } from './components/people/people.component';
import { OthersComponent } from './components/others/others.component';

const routes: Routes = [
  {
    path: 'products',
    loadChildren: () => import('./products/products.module').then(m => m.ProductsModule)
  }
];

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

se importa por medio del método de lazy loading el product module, el cual tiene su propio archivo de rutas. Que funciona de la siguiente manera

products-routing.module.ts

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { ProductDetailComponent } from './components/product-detail/product-detail.component';
import { ProductsComponent } from './components/products/products.component';

const routes: Routes = [
  {
    path: '',
    component: ProductsComponent
  },
  {
    path: ':id',
    component: ProductDetailComponent
  }
];

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

Ahora con esto se puede ver que al entrar al módulo de productos se vera el componente de products, tambien con se encuentra una ruta con un id que representa la identificación de cada componente que redirige al componente ProductDetail.

Lo siguiente sera ver el comportamiento de productsComponent

products.component.ts

import { Component, OnInit } from '@angular/core';
import { Product } from '../../../models/product.model';
import { ProductsService } from '../../../services/product.service';
import { ValueService } from '../../../services/value.service';

@Component({
  selector: 'app-products',
  templateUrl: './products.component.html',
  styleUrls: ['./products.component.scss']
})

export class ProductsComponent implements OnInit {
  products: Product[] = [];
  limit = 10;
  offset = 0;
  status: 'loading' | 'success' | 'error' | 'init'= 'init';
  rta: string = '';

  constructor(
    private productsService: ProductsService,
    private valueService: ValueService,
  ) { }

  ngOnInit(): void {
    this.getAllProducts();
  }

  getAllProducts() {
    this.status = 'loading';
    this.productsService.getAll(this.limit, this.offset)
    .subscribe({
      next: (products) => {
        this.products = [...this.products, ...products];
        this.offset += this.limit;
        this.status = 'success';
      },
      error: (error) => {
        setTimeout(() => {
          this.products = [];
          this.status = 'error';
        }, 3000);
      }
    });
  }

  async callPromise () {
    const rta = await this.valueService.getPromiseValue();
    this.rta = rta;
  }
}

products.component.html

<section class="container">
  <h1>Products Component</h1>
  <h3>Rta</h3>
  <button class="btn-promise" (click)="callPromise()">Call promise</button>
  <p class="rta">{{ rta }}</p>
  <div class="my-grid">
    <app-product
      *ngFor="let product of products"
      [product]="product">
  </app-product>
  </div>
  <button class="btn-products" [disabled]="status === 'loading'" (click)="getAllProducts()">
    <span *ngIf="status === 'init' || status === 'success'">Load more</span>
    <span *ngIf="status === 'loading'">Loading...</span>
    <span *ngIf="status === 'error'">Error</span>
    </button>
</section>

products component obtendra todos los productos desde la API y los renderizara uno por uno por medio del componente app-product, ademas dentro de app-product se encuentra un link de ingreso al detalle de cada producto

product.component.ts

<div>
  <figure>
    <img [src]="product.images[0]" alt="">
    <figcaption>
      {{product.title}} - {{product.price}}
    </figcaption>
  </figure>
  <p>{{ product.description }}</p>
  <a [routerLink]="['./', product.id]">Ver detalle</a>
</div>

Nota: product.component no tiene lógica de negocio en typescript debido a que solo se ocupa de renderizar cada producto mediante un html

product-detail.ts

import { Component, OnInit } from '@angular/core';
import { Location } from '@angular/common';
import { ActivatedRoute } from '@angular/router';
import { switchMap } from 'rxjs/operators';
import { Product } from '../../../models/product.model'
import { ProductsService } from '../../../services/product.service';

@Component({
  selector: 'app-product-detail',
  templateUrl: './product-detail.component.html',
  styleUrls: ['./product-detail.component.scss']
})

export class ProductDetailComponent implements OnInit {
  product: Product | null = null;
  constructor(
    private route: ActivatedRoute,
    private productsService: ProductsService,
    private location: Location
  ) { }

  ngOnInit(): void {
    this.route.paramMap
      .subscribe((params) => {
        const productId = params.get('id');
        if (productId) {
          this.getProductDetail(productId);
        } else {
          this.goToBack();
        }
      });
  }

  private getProductDetail(productId: string) {
    this.productsService.getOne(productId)
    .subscribe({
      next: (product) => {
        this.product = product;
      },
      error: () => {
        this.goToBack();
      }
    })
  }

  goToBack() {
    this.location.back();
  }
}

Ahora obtendremos la lógica del product-detail y su renderización

product-detail.html

<section class="container">
  <article>
    <a (click)="goToBack()">Back</a>
    <div class="detail" *ngIf="product">
      <figure>
        <img [src]="product.images[0]" alt="">
      </figure>
      <div>
        <h1>{{ product.title }}</h1>
        <h2>{{ product.price | currency }}</h2>
      </div>
    </div>
  </article>
</section>