具有角度2错误的MEAN应用程序:无法读取未定义的属性_id

时间:2017-09-12 05:02:47

标签: javascript angular typescript mean-stack

我是第一次构建应用程序来存储,更新,查看和删除客户端配置文件。我按照Angular的英雄之旅来构建基本应用程序,然后将mongodb拼凑在一起并表达网络周围的部分。

当我尝试删除客户端配置文件时,我在浏览器控制台中收到此错误 -

  

错误TypeError:无法读取未定义的属性“_id”       在ClientProfileComp.webpackJsonp ... / .. / .. / .. / .. / src / app / components / clientProfile.component.ts.ClientProfileComp.delete   (clientProfile.component.ts:53)......(等)。

我已经确认使用邮递员,我的快递路由按预期工作。我可以在/api/clients获取所有/创建客户端,以及从/api/clients/:_id获取,放置和删除(其中_id是每个条目的自动生成的ID)。

我认为问题出在我的一个组件文件中,因为只有在我尝试删除或查看特定客户端详细信息时才会出现错误,这会导致另一种类型的错误(CastError)。当我尝试删除clientProfile: ClientProfile[];(或教程中的Hero)的所有提及时,问题可能开始了,因为我不再从client.ts(hero.ts)导入细节,因为我正在使用一个mongoose模式,我不相信我应该将该模式导入我的前端角度。

这是clientProfile.service.ts的删除部分:

delete(_id: number): Promise<void>  {
    const url = `${this.clientProfilesUrl}/${_id}`;
    return this.http.delete(url, {headers: this.headers}).toPromise()
    .then(() => null).catch(this.handleError);
}

,这里是clientProfile.component.ts(请问我的问题最可能的原因是我用clientProfile: ClientProfile;替换了clientProfile: any;的所有实例而不知道我在做什么 请注意注释掉的导入语句。

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';

//import { ClientProfile } from '../old/clientProfile';
import { ClientProfileService } from '../services/clientProfile.service';

@Component({
selector: 'app-clientprofile',
templateUrl: '../views/clientProfile.component.html',
styleUrls: [ '../styles/clientprofile.component.css' ]
})

export class ClientProfileComp implements OnInit {
selectedClientProfile: any;
clientProfiles: any = [];
clientProfile: any;

constructor(
    private clientProfileService: ClientProfileService,
    private router: Router
) { }

gotoDetail(): void {
    this.router.navigate(['/detail', this.selectedClientProfile._id]);
}

getClientProfiles(): void {
    this.clientProfileService.getClientProfiles().then(clientProfiles => {
        this.clientProfiles = clientProfiles;
    });
}

ngOnInit(): void {
    this.getClientProfiles();
}

onSelect(clientProfile: any): void {
    this.selectedClientProfile = clientProfile;
}

add(name: string, address: string): void {
    name = name.trim();
    address = address.trim();
    if (!name) { return; }
    this.clientProfileService.create(name, address).then(clientProfile => {
        this.clientProfiles.push(clientProfile);
            this.selectedClientProfile = null;
    this.getClientProfiles();
    });
}

delete(clientProfile: any): void {
    this.clientProfileService.delete(clientProfile._id).then(() => {
        this.clientProfiles = this.clientProfiles.filter(h => h !== 
clientProfile);
        if (this.selectedClientProfile === clientProfile) { this.selectedClientProfile = null; }
    });
}
}

我一直在研究这一天,并且在这里也阅读了很多类似的帖子 - 但大多数解决方案似乎并不适用于这种情况。如果有人能指出我正确的方向,我会非常感激。如果需要更多代码来解释我正在尝试做什么,我会很乐意发布它。

2 个答案:

答案 0 :(得分:0)

根据错误消息,似乎错误在这里:

this.router.navigate(['/detail', this.selectedClientProfile._id])

您似乎只在onSelect中进行了设置,并且您的代码中有几个地方将this.selectedClientProfile设置为null。那将是最好看的地方。

如果您想创建一个能够展示您问题的plunker,我们可以进一步了解它。

作为旁注,您使用的是promises而不是现在更常见的Observable。如果您想要切换到使用Observables,我在这里有一个完整的CRUD(创建,读取,更新和删除)操作示例:APM文件夹中的https://github.com/DeborahK/Angular2-ReactiveForms

答案 1 :(得分:0)

发现一个问题 - 我的html文件中的删除按钮位于div中,该div仅在选择客户端时出现,而不是在每个客户端旁边。这是我采取的半成品措施的结果,以确保用户不会在每个客户端上单击“删除”。

之前的代码:

'expire_on_close' => false

现在代码:

<h2>Client Profiles</h2>
<div class="add-client">
<label>Add new client</label>
<input placeholder="Client Name (required)" #clientProfileName />
<input placeholder="Client Address" #clientProfileAddress />
<button (click)="add(clientProfileName.value, clientProfileAddress.value); 
clientProfileName.value=''; clientProfileAddress.value=''">
    Add</button>
</div>
<ul class="clientProfiles">
<li *ngFor="let clientProfile of clientProfiles"
    [class.selected]="clientProfile === selectedClientProfile"
    (click)="onSelect(clientProfile)">
    <span class="badge">{{clientProfile.idnumber}}</span>
    <span>{{clientProfile.name}}</span>
</li>
</ul>
<div *ngIf="selectedClientProfile">
<h2>
    {{selectedClientProfile.name | uppercase}} selected
</h2>
<button (click)="gotoDetail()">View Details</button>
<button class="delete"
        (click)="delete(clientProfile); 
$event.stopPropagation()">Delete</button>
//delete button will only appear when a client is selected
</div>