无法读取未定义 CRUD 操作的“_id”类型的属性

Posted

技术标签:

【中文标题】无法读取未定义 CRUD 操作的“_id”类型的属性【英文标题】:Cannot read property of type '_id ' of undefined CRUD operations 【发布时间】:2021-06-20 09:27:08 【问题描述】:

我对 Angular 还很陌生,只是实现了 CRUD 操作。我正在使用一个快递服务器,它使用猫鼬作为我的后端,而前端是有角度的。

我的快递服务器工作正常,我可以处理所有请求,并且可以获取要在我的 Angular 应用程序中显示的产品列表。

当我单击产品或尝试删除产品时,我得到“无法读取类型为 '_id' 的属性 未定义”

我的问题是如何使用他们的 ID 定义我单击或删除的特定产品,因为这是删除请求所需要的,或者我在哪里出错了?我也不太了解未定义的错误,因为我可以获取所有产品并显示它们的 id、名牌等。

我在我的产品模型和 isbn 中使用 _id,因为在邮递员中创建的 id 使用 _id,这是我需要删除的。

这是我的产品服务

import  Injectable  from '@angular/core';
import IProduct from 'model/product'
import  HttpClient, HttpErrorResponse, HttpHeaders  from '@angular/common/http';
import  Observable, of, throwError  from 'rxjs';
import  catchError, map, tap  from 'rxjs/operators'

@Injectable(
  providedIn: 'root'
)
export class ProductService 

  private dataUri ='http://localhost:5000/Beauty'

  constructor(private http: HttpClient)  

  getProducts():Observable<IProduct[]>

    console.log("get products called"); 

    return this.http.get<IProduct[]>(`$this.dataUri?limit=10`)
      .pipe(
        catchError(this.handleError
          )
      )
  

  getProductById(id: string): Observable<any>
    return this.http.get(`$this.dataUri/$id`)
  

  addProduct(product: IProduct): Observable<IProduct>
    return this.http.post<IProduct>(this.dataUri, product)
    .pipe(
      catchError(this.handleError)
    )
  

  updateProduct(id:string, product: IProduct): Observable<IProduct>
    console.log('subscrbing to update' + id); 
    let productURI: string = this.dataUri + '/' + id; 
    return this.http.put<IProduct>(productURI, product)
    .pipe(
      catchError(this.handleError)
    )
  

  deleteProduct(_id : string) : Observable<IProduct>
    let productURI: string = this.dataUri + '/' + (_id); 
    return this.http.delete<IProduct>(productURI)
    .pipe(
      catchError(this.handleError)
    )
  
   

  private handleError(error: HttpErrorResponse) 
    if (error.error instanceof ErrorEvent) 
      // A client-side or network error occurred. Handle it accordingly.
      console.error('An error occurred:', error.error.message);
     else 
      // The backend returned an unsuccessful response code.
      // The response body may contain clues as to what went wrong.
      console.error(
        `Backend returned code $error.status, ` +
        `body was: $error.error`);
    
    // Return an observable with a user-facing error message.
    return throwError(
      'Something bad happened; please try again later.');
  




这里是 product-crud 组件

import  Component, OnInit  from '@angular/core';
import  Router  from '@angular/router';
import IProduct from 'model/product'
import  Observable  from 'rxjs';
import  ProductService  from '../product.service';

@Component(
  selector: 'app-product-crud',
  templateUrl: './product-crud.component.html',
  styleUrls: ['./product-crud.component.css']
)
export class ProductCrudComponent implements OnInit 

  products: IProduct[];  
  message:string;

  currentproduct: IProduct; 

  constructor(private productservice: ProductService, 
    private router: Router)  
  ngOnInit(): void 
    this.loadProducts(); 
  

  clicked(product: IProduct):void
    this.currentproduct = product; 
    console.log(this.currentproduct._id); 
  
  loadProducts()

    this.productservice.getProducts().subscribe(
      next:(value: IProduct[])=> this.products = value, 
      complete: () => console.log('product service finished'), 
      error:(mess) => this.message = mess
    )

  
  deleteProduct(_id: string, product: IProduct)
  
    console.log('deleting product'); 

    this.productservice.deleteProduct(product._id)
    .subscribe(
      next:product => this.message = "product is deleted", 
      complete: () => console.log("deleted product"), 
      error: (mess) => this.message = mess
    )
  
     updateProduct(_id: string)
      this.router.navigate(['update', _id]);
    



和product-crud组件html

<div class="panel panel primary">
    <div class="panel-heading">
        <h2>Product List</h2>
    </div>

    <div class="panel-body">
        <table class="table table-striped">
            <thead>
                <tr>
                    <th>
                        Name
                    </th>
                    <th>
                        Category
                    </th>
                    <th>
                        Brand
                    </th>
                    <th>
                        Price
                    </th>
                    <th>
                        id
                    </th>
                </tr>
            </thead>
            <tbody>
                <tr *ngFor="let product of products"
                [product] = "p"
                (click) = 'clicked(p)'>
                    <td>product.name</td>
                    <td>product.category</td>
                    <td>product.brand</td>
                    <td>product.price</td>
                    <td>product.isbn</td>
                    <td><button (click)="deleteProduct(product.id)" class="btn btn-danger">Delete</button>
                       <button (click)="updateProduct(product.id)" class="btn btn-info" style="margin-left: 10px">Update</button>
                        <button (click)="detailproduct(product.id)" class="btn btn-info" style="margin-left: 10px">Details</button> 
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
</div>

【问题讨论】:

你在邮递员中试过这个吗?可能是 api 的问题,或者您没有传递正确的 id。 mongo 使用 _id,如果您的产品有单独的 id,请确保您将正确的 id (deleteProduct(product.**id**)) 传递给 api 调用。 谢谢,但是我已经在邮递员中尝试过。我有一个产品 id 和另一个用于实际发出删除请求所需的“id”。我为此使用 _id。 &lt;tr *ngFor="let product of products" [product] = "p" (click) = 'clicked(p)'&gt; 不应该是 &lt;tr *ngFor="let product of products" (click) = "clicked(product)"&gt; 吗?另外 [product] 应该给你一些编译时错误。 @GowthamRajJ 谢谢,这解决了我的点击错误。我不确定如何将其应用于删除功能。我试图让它类似于点击功能,但我仍然收到未定义的错误。你知道为什么会这样吗? 【参考方案1】:

查看您在组件中的功能,以下更改应该可以使其工作。

    &lt;tr *ngFor="let product of products" (click) = "clicked(product)"&gt; 这里的产品是你需要传递的局部变量。

    另外,函数签名deleteProduct(product.id) 和函数调用(click)="deleteProduct(product.id)" 不匹配。

您可能希望将这些更改为(click)="deleteProduct(product._id, product)"。同样检查和修改其他函数调用。

【讨论】:

非常感谢!删除功能现在正在工作。混淆了 ID,没有使用数组。 很高兴能帮上忙 :)

以上是关于无法读取未定义 CRUD 操作的“_id”类型的属性的主要内容,如果未能解决你的问题,请参考以下文章

删除模态。反应 Redux。无法读取未定义的属性“_id”

Angular Karma - TypeError:无法读取未定义的属性“_id”

TypeError:无法读取 MEAN 堆栈中未定义的属性“_id”

无法读取未定义 MongoDB 的属性“集合”

TypeError:无法读取未定义的属性(读取“匹配”):

NestJS/TypeORM:无法读取未定义的属性“createQueryBuilder”