在 ANGULAR 中使用 HTTP 从服务获取数组列表
我有一个名为 zoomdetails 的组件,其中包含产品的具体详细信息 当我单击产品图片时,zoomdetails 组件会显示并包含所单击产品的详细信息
因此,我正在使用路由并将产品的 id 添加到 URL
问题是:
当我从服务加载产品数组列表并尝试通过其 id 获取产品并循环数组列表时,出现错误并指示 无法读取未定义的属性“长度”
这是 zoomdetails.component.ts 代码: (我添加了一些 log.console 注释以查看结果)
export class ZoomdetailsComponent implements OnInit {
x: string="";
produitzoom:IProduct;
produits:IProduct[];
errormessage1 :string ;
currentId : number;
constructor(private _route:ActivatedRoute,private _router:Router,private _productServic:ProductdataService)
{
console.log("Logging the route : " + JSON.stringify(_route.snapshot.params));
this.currentId = +_route.snapshot.params['id'];
console.log("Logging the current ID : " + this.currentId)
this._productServic.getProducts()
.subscribe(productss => this.produits=productss ,error=>this.errormessage1= <any>error);
console.log("************************************************************************************")
}
Myspan(){
this._router.navigate(['/']);
}
find (id:number,P:IProduct[]) :IProduct{
console.log("+++++++DANS FIND ERROR +++++++++++++++++++++++++")
for (let product of P )
{
if (product.idpr==id )
{
return product;
}
}
}
ngOnInit() {
console.log("-------------DANS NGONINITTT-------------------------------------------------------------")
this.produitzoom=this.find(this.currentId,this.produits)
console.log(this.produitzoom.productName)
console.log("--------------------------------------------------------------------------")
}
这是我的 zoomdetails 组件 .html
<router-outlet></router-outlet>
<div id="zoom" class="modal">
<!-- Modal content -->
<div class="modal-content">
<span class="close" (click)="Myspan()">×</span>
<div class="container">
<div class="row">
<div class="col-md-4 item-photo">
<img src={{produitzoom.imgUrl}} style="width:360px;height:650px;">
</div>
<div class="col-md-6" style="border:0px solid rgba(163, 152, 152, 0.856)">
<span class="pull-right">
<!-- Datos del vendedor y titulo del producto -->
<h1>{{produitzoom.productName}}</h1>
<h4 style="color:#337ab7"> {{produitzoom.author}} <small style="color:#337ab7">(50 ventes)</small></h4>
<!-- Precios -->
<h2 class="title-price"><small>Price</small></h2>
<h3 style="margin-top0px">{{produitzoom.price}} $</h3>
<br> <br>
<!-- Detalles especificos del producto -->
<div class="section" style="background:rgb(222, 228, 222);">
<h5 class="title-attr" >
<div>
<br>
{{produitzoom.description}}
<br> <br>
</div>
</h5>
</div>
<br><br>
<!-- Botones de compra -->
<script>
console.log("Test of value : " + JSON.stringify(produitzoom))
</script>
<button class="btn btn-success right" [routerLink]="['/Authentification',produitzoom]">
<span class="glyphicon glyphicon-shopping-cart"></span> Add to Cart
</button>
</span>
<br> <br> <br> <br>
<ul class="menu-items">
<li class="active">Customers Reviews</li>
</ul>
<div style="width:100%;border-top:1px solid silver">
<p style="padding:15px;">
<small>
Stay connected either on the phone or the Web with the Galaxy S4 I337 from Samsung. With 16 GB of memory and a 4G connection, this phone stores precious photos and video and lets you upload them to a cloud or social network at blinding-fast speed. With a 17-hour operating life from one charge, this phone allows you keep in touch even on the go.
With its built-in photo editor, the Galaxy S4 allows you to edit photos with the touch of a finger, eliminating extraneous background items. Usable with most carriers, this smartphone is the perfect companion for work or entertainment.
</small>
</p>
</div>
</div>
</div>
</div>
</div>
</div>
这些是错误:
Logging the route : {"id":"1"} zoomdetails.component.ts:22 Logging the current ID : 1 zoomdetails.component.ts:25 ************************************************************************************ zoomdetails.component.ts:50 -------------DANS NGONINITTT------------------------------------------------------------- zoomdetails.component.ts:38 +++++++DANS FIND ERROR +++++++++++++++++++++++++ ZoomdetailsComponent_Host.html:1 ERROR TypeError: Cannot read property 'length' of undefined (from the find method )
错误 TypeError:无法读取未定义的属性“imgUrl”(来自 html 文件 produitzoom.imgurl)
我该怎么办!
首先,关于
imgUrl
错误,由于最初
produitzoom
未定义,并且它在异步调用后获取其值,您可以将绑定的值更改为:
[src]="produitzoom? produitzoom.imgUrl : null"
。
同样关于另一个错误,您正在
ngOnInit
函数内调用
this.produitzoom=this.find(this.currentId,this.produits)
,但同样,由于
produits
在组件生命周期开始时也是未定义的,并在异步调用后获取其值。您应该将
this.find()
调用移至订阅成功。类似这样的内容:
productss => {
this.produits=productss;
this.produitzoom = this.find(this.currentId,this.produits)
}
注意!
同样非常重要且建议的是,如果您订阅了可观察对象,则在该组件的生命周期结束时取消订阅(在
ngOnDestroy
函数内)。否则,这会导致内存泄漏和无法追踪的错误……您可以通过定义订阅的属性来实现这一点,例如:
productsSubscription:Subscription;
不要忘记从
rxjs/subscription
导入
Subscription
。然后将订阅分配给此属性,例如:
this.productsSubscription = this._productServic.getProducts()
.subscribe(.....);
并在 ngOnDestroy 内:
ngOnDestroy(){
if(this.productsSubscription){
this.productsSubscription.unsubscribe();
}
}
在那里使用
if
来防止任何与未定义相关的错误。
问题在于,您在构造函数中加载产品,这是异步的。然后在稍后调用的
ngOnInit
函数中,您将使用这些已加载产品的结果,但不幸的是,它们似乎尚未加载。因此,您的
P
数组尚不存在,因此您在 for 循环中使用了未定义的对象,这是行不通的。
ngOnInit() {
console.log("-------------DANS NGONINITTT-------------------------------------------------------------")
// --> here you use the products from the constructor
// but they are not loaded yet, because the loading process takes time and is asynchronous
this.produitzoom=this.find(this.currentId,this.produits)
console.log(this.produitzoom.productName)
console.log("--------------------------------------------------------------------------")
}
您应该做的是将产品的加载也放在
ngOnInit
函数中。在那里,您可以等待结果,然后调用 find 函数。
nOnInit(){
// don't subscribe in the constructor, do it in the ngOnInit
this._productServic.getProducts().subscribe(productss => {
// now the results are here and you can use them
this.produits = productss;
// only then you can call the find function safely
this.produitzoom = this.find(this.currentId, this.produits)
}, error => this.errormessage1 = <any>error);
}