Product Detail

Clase 3 de 20 • Curso de Angular: Unit Testing para Rutas

Clase anteriorSiguiente clase
    Cesar Elías Armendariz Ruano

    Cesar Elías Armendariz Ruano

    student•
    hace 3 años

    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">   <h2>Products Component</h2>   <h4>Rta</h4>   <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>         <h2>{{ product.title }}</h2>         <h3>{{ product.price | currency }}</h3>       </div>     </div>   </article> </section>