在ANGULAR中使用HTTP从服务中获取一个arraylist

时间:2017-11-26 12:02:03

标签: json angular http service

我有一个名为zoomdetails的组件,其中包含产品的特定详细信息  当我点击产品图片时,zoomdetails组件会显示并包含所点击产品的详细信息

所以我使用路由并将产品的ID添加到URL

问题是:

当我从服务加载产品arraylist并尝试通过其id获取产品并循环arraylist时出现错误并指示无法读取属性' length'未定义的

这里是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("--------------------------------------------------------------------------")
  
  
}
&#13;
&#13;
&#13;

这是我的zoomdetails组件.html

&#13;
&#13;
<router-outlet></router-outlet>
<div id="zoom" class="modal">
  
    <!-- Modal content -->
    <div class="modal-content">
    <span class="close" (click)="Myspan()">&times;</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>
&#13;
&#13;
&#13;

这些是错误:

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 )

错误类型错误:无法读取属性&#39; imgUrl&#39;未定义的(来自html文件produitzoom.imgurl)

我应该怎么做!

2 个答案:

答案 0 :(得分:1)

首先,关于imgUrl错误,因为最初produitzoom未定义,并且在异步调用后获得它的值,您可以将绑定的值更改为这个:[src]="produitzoom? produitzoom.imgUrl : null"

还有关于另一个错误,你在this.produitzoom=this.find(this.currentId,this.produits)函数中调用了ngOnInit,但同样重要的是,在组件的开头部分produits也未定义的事实&# 39; s生命周期,并在异步调用后获取它的值。您应该将this.find()移动到订阅的成功。像这样的东西:

productss => {
    this.produits=productss;
    this.produitzoom = this.find(this.currentId,this.produits)
}

注意!!

它也非常重要,并建议如果您订阅了一个observable,则在该组件的生命周期(ngOnDestroy函数内)的末尾取消订阅它。否则,这会导致内存韭菜和无法纠正的错误......你可以通过定义订阅属性来做到这一点: productsSubscription: Subscription; 别忘了从Subscription导入rxjs/subscription。然后将订阅分配给此属性,如:

this.productsSubscription = this._productServic.getProducts()
    .subscribe(.....);

并且在ngOnDestroy中:

ngOnDestroy(){
    if(this.productsSubscription){
        this.productsSubscription.unsubscribe();
    }
}

让那里if来防止任何与未定义相关的错误。

答案 1 :(得分:0)

问题是您在构造函数中加载产品,这是异步的。然后在您稍后调用的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);
}