Home > Enterprise >  Angular: Routing Observable Binding = ngtsc(2339)
Angular: Routing Observable Binding = ngtsc(2339)

Time:06-14

I have an Angular Component called "crear-pedido" that shows a list of items (let row of products) and I want the user to be able to click the ID column values and route the app to a child component called "detalle-productos". In essence: a list of products where if you click the product.ID a card shows up displaying the details of the product.

Relevant routing config:

const routes: Routes = [
  { path: 'crear-pedido', component: CrearPedidoComponent,
  children: [
    {path: ':ID', component: DetalleProductosComponent},
  ]},
];

I'm passing the row.ID data to the child component like so:

<td mat-cell *matCellDef="let row"><a [routerLink]="['/crear-pedido', row.ID]">  {{row.ID}} </a> </td>

This is the "detalle-productos.component.ts" file:

import { Component, OnInit } from '@angular/core';
import { Producto_interface } from '../producto_interface';
import product_list from '../product_json.json' 
import { ActivatedRoute } from '@angular/router';
import { Observable, switchMap } from 'rxjs';

@Component({
  selector: 'app-detalle-productos',
  templateUrl: './detalle-productos.component.html',
  styleUrls: ['./detalle-productos.component.css']
})
export class DetalleProductosComponent implements OnInit {
  productos: Producto_interface [] = product_list;
  selectedProduct: Observable<Producto_interface>;
  
  constructor(private route: ActivatedRoute) { }

  ngOnInit() {
    this.selectedProduct = this.route.paramMap.pipe(
      switchMap(params => {
        const id = params.get('ID');
        console.log("Inside oninit")
        console.log(this.productos.filter(p => p.ID.toString() == id?.toString()))
        return this.productos.filter(p => p.ID.toString() == id?.toString())
      })
    )
  }
}

As you can see, the component gets the JSON file with all the products into "product_list" and the ngOnInit() method receives the routed value and filters the product_list to find the right product. Goal is to pass the product info to selectedProduct and then display that in the HTML.

The console.log right before the return is working properly:

0: Object { ID: "606", Nombre: "Tapitas Gran Valle Galleta Blanca 9 KG", Linea: "Tapitas", … }

Here is the relevant HTML:

<mat-card  *ngIf="selectedProduct | async as Producto_interface">
    <mat-card-subtitle>Marca: {{selectedProduct['Marca']}}</mat-card-subtitle>
    <mat-card-title>{{selectedProduct['Nombre']}}</mat-card-title>
    <mat-card-content>
        <p>Código interno: {{selectedProduct['ID']}}</p>
        <p>Sabor: {{selectedProduct['Sabor']}}</p>
        <p>Envase: {{selectedProduct['Envase']}}</p>
        <p>Línea: {{selectedProduct['Linea']}}</p> 
    </mat-card-content> 
    <button mat-raised-button routerLink="/crear-pedido" color="primary">Cerrar</button>
</mat-card>

Problem is, when you click the ID, the card appears but it is completely empty.

I am quite new to Angular and struggling to figure out the whole Observable<> and strict types ordeal. I had to add:

"noImplicitAny": false,

To the tsconfig.json file in order to get it to compile. I'm fairly sure the right syntax would be:

selectedProduct.Marca

Instead of selectedProduct['Marca']

But if I do that I get the following error:

Property 'Marca' does not exist on type 'Observable<Producto_interface>'.ngtsc(2339)

I've checked around a dozen different threads on similar issues, but after trying every single solution, this is how far I got.

Help me, Stackoverflowers. You are my only hope.

CodePudding user response:

You have an Observable that you want to display, this means that you have to use the async pipe:

<mat-card-subtitle>Marca: {{(selectedProduct|async)?.marca}}</mat-card-subtitle>

Will subscribe to the selectedProduct and then display the value of the marca attribute.

Or you have to use it with your local variable, but name it correctly:

*ngIf="selectedProduct | async as product"

and then use it in the HTML block:

 <mat-card-subtitle>Marca: {{product?.marca}}</mat-card-subtitle>

  • Related