Tengo un componente en mi aplicación angular5 llamado: product-list.component.ts. En este componente tengo un constructor, que llama a una API REST.

product.service.ts

getAllProductsFromACategory(categoryName: string): any {
this.http.get('http://localhost:8080/VespaWebshopAPI
/api/Article/Category?categoryName=' + categoryName).
subscribe(data => {
var article: Article = {
    id: data[0].id,
    name: data[0].name,
    articleNr: data[0].articleNr,
    stock: data[0].stock,
    price: data[0].price,
    description: data[0].description
  };

  return article;
}); 

product-list.component.ts

public article: Article;

constructor(private route: ActivatedRoute, 
private productService: productService) { 
 //Call rest api
 this.article = 
 this.productService.getAllProductsFromACategory('Bremsen');
}

article.ts

export interface Article {
id : number;
name : string;
articleNr : string;
stock : number;
price : number;
description : string;
}

En mi html, quiero mostrar algunas propiedades de un artículo. Entonces, si intento ejecutar este código en mi archivo product-list.component.html , aparece el siguiente error:

{{ article.id }}

Error

ProductListComponent.html: 1 ERROR TypeError: no se puede leer la propiedad 'id' de indefinido
en Object.eval [como updateRenderer] (ProductListComponent.html: 1)
en Object.debugUpdateRenderer [como updateRenderer] (core.js: 14727)
en checkAndUpdateView (core.js: 13841)
en callViewAction (core.js: 14187)
en execComponentViewsAction (core.js: 14119)
en checkAndUpdateView (core.js: 13842)
en callViewAction (core.js: 14187)
en execEmbeddedViewsAction (core.js: 14145)
en checkAndUpdateView (core.js: 13837)
en callViewAction (core.js: 14187)

La API REST funciona; Lo probé Supongo que existe el problema de que los datos deben cargarse primero, antes de que se muestre la página html. En otro lugar leí que en un ngFor, debería hacer uso de | tubería asíncrona, pero eso no funcionó para mí.

Entonces, ¿cómo resuelvo esto?

7
Ird 14 ene. 2018 a las 17:25

3 respuestas

La mejor respuesta

@TNII, @Hoang Duc, intenta decir que, en general, un servicio expone a Observables. Está en un ngOnInit en su componente cuando se suscribe al Observable.

//Simple return a get
getAllProductsFromACategory(categoryName: string): any {
   return this.http.get('http://localhost:8080/VespaWebshopAPI
   /api/Article/Category?categoryName=' + categoryName)
}

En el componente, generalmente en un ngOnInit cuando nos suscribimos a

ngOnInit()
{
    productService.getAllProductsFromACategory('Bremsen').
      subscribe(data => {
         if (data[0])
             this.article=data[0];
      })
}

El {{artículo? .id}} escrito en el html es una forma abreviada de decir: si this.article está definido, muéstrame this.article.id.

Compruebe si en un navegador escriba http: // localhost: 8080 / VespaWebshopAPI / api / Article / Category? categoryName = 'Bremsen', le ofrece una variedad de artículos. Compruebe si los elementos de las matrices tienen propiedades id, nombre, etc. (o devuelva el elemento con otras propiedades)

6
Eliseo 14 ene. 2018 a las 16:24

En productService.getAllProductsFromACategory() reemplace subscribe con map para que el método devuelva Observable<Article>

En constructor de product-list.component.ts, suscríbase al Observable<Article> devuelto por productService y establezca el valor para this.article en ese

this.productService.getAllProductsFromACategory('Bremsen')
    .subscribe((art: Article) => {
        this.article = art;
    },
    (err: any) => console.error(err));

En su html, coloque un *ngIf="article" en el elemento circundante de su interpolación {{ article.id }} para evitar que se procese hasta que article obtenga un valor válido.

5
Hoang Duc Nguyen 14 ene. 2018 a las 14:36

El problema es que la plantilla está tratando de usar datos que aún no están disponibles. Antes de acceder, se debe completar la respuesta del servidor. Entonces, para "esperar y evitar ese error", hice un truco similar que funcionó bien.

Escribí una directiva condicional sobre el elemento circundante. Al hacerlo, "mientras data_from_server es nulo", la plantilla no intenta obtener la información y no produce el error.

<div style="text-align:center" *ngIf="data_from_server">
  <form>
    <label for="name">NAME</label> 
    <input [(ngModel)]="data_from_server.nombre" name="nombre">
  </form>
 </div>
-2
Val Martinez 2 abr. 2018 a las 16:58