简体   繁体   English

无法读取角度2中记录编辑表单中未定义的属性

[英]Cannot read property of undefined in record edit form in angular 2

I have a problem in my edit form with undefined properties. 我的编辑表单中存在未定义属性的问题。 I have an API that allows me to create and update customers. 我有一个API,可用来创建和更新客户。 The problem is that some of the nested attributes are optional, this is fine when creating or editing fields that already exist but i can't figure out what to do when editing one of the nested fields on a customer that wasn't created with those fields and keep getting Cannot read property undefined errors. 问题是某些嵌套属性是可选的,这在创建或编辑已存在的字段时很好,但是当在未使用这些属性创建的客户上编辑其中一个嵌套字段时,我不知道该怎么做字段并不断获取无法读取属性未定义的错误。

This is my customer object: 这是我的客户对象:

export class Customer { 
  CompanyName: string;
  DisplayName: string;
  FamilyName: string; 
  GivenName: string;
  Id: number;
  Title: string;
  BillAddr: BillAddress;
  ShipAddr: ShipAddress;
  PrimaryPhone:  PrimaryPhoneNumber;
  Mobile: MobileNumber;
  PrimaryEmailAddr: PrimaryEmailAddress;
 }


  export class ShipAddress {
   City: string;
   Country: string;
   CountrySubDivisionCode: string; 
   Line1: string;
   Line2: string; 
   Line3: string; 
   Line4: string; 
   Line5: string; 
   PostalCode:string;
 }

   export class BillAddress {
   City: string;
   Country: string;
   CountrySubDivisionCode: string; 
   Line1: string;
   Line2: string; 
   Line3: string; 
   Line4: string; 
   Line5: string; 
   PostalCode:string;
 }

  export class PrimaryPhoneNumber {
    FreeFormNumber: number;
  }

  export class MobileNumber {
    FreeFormNumber: number;
  }

  export class PrimaryEmailAddress {
    Address: string; 
  }

This is the html from the edit component: 这是来自edit组件的html:

<h1 class="page-header">Edit Customer</h1>
<div [ngBusy]="busy"></div>
<form (ngSubmit)="onSubmit()">
<div class="row">
<div class="col-md-6">
<h3>Customer information</h3>
<div class="form-group">
    <label for="customertitle">Title</label>
    <input type="text" class="form-control" id="cutomertitle" placeholder="Title" name="title" [(ngModel)]="customer && customer.Title" >
</div>
<div class="form-group">
    <label for="customerGivenName">First Name</label>
    <input type="text" class="form-control" id="customerGivenName" placeholder="First Name" name="givenname" [(ngModel)]="customer && customer.GivenName" >
</div>
<div class="form-group">
    <label for="customerFamilyName">Last Name</label>
    <input type="text" class="form-control" id="customerFamilyName" placeholder="Surname" name="familyname" [(ngModel)]="customer && customer.FamilyName" >
</div>
<div class="form-group">
    <label for="customerEmailAddress">Email Address</label>
    <input type="text" class="form-control" id="customerEmailAddress" placeholder="Email" name="email" [(ngModel)]="customer && customer.PrimaryEmailAddr.Address" >
</div>
<div class="form-group">
    <label for="customerPhone">Phone</label>
    <input type="text" class="form-control" id="customerPhone" placeholder="Phone Number" name="primaryphone" [(ngModel)]="customer && customer.PrimaryPhone.FreeFormNumber" >
</div>
<div class="form-group">
    <label for="customerMobile">Mobile</label>
    <input type="text" class="form-control" id="customerMobile" placeholder="Mobile Number" name="mobile" [(ngModel)]="customer && customer.Mobile.FreeFormNumber" >
</div>
</div>

<div class="col-md-6">
<h3>Address:</h3>
<div class="form-group">
    <label for="customerLine1">Line 1</label>
    <input type="text" class="form-control" id="cutomerLine1" placeholder="Line 1" name="line1" [(ngModel)]="customer && customer.BillAddr.Line1" >
</div>
<div class="form-group">
    <label for="customerLine1">Line 2</label>
    <input type="text" class="form-control" id="cutomerLine2" placeholder="Password" name="line2" [(ngModel)]="customer && customer.BillAddr.Line2" >
</div>
<div class="form-group">
    <label for="customerLine1">Line 3</label>
    <input type="text" class="form-control" id="cutomerLine3" placeholder="Password" name="line3" [(ngModel)]="customer && customer.BillAddr.Line3" >
</div>
<div class="form-group">
    <label for="customerCity">City</label>
    <input type="text" class="form-control" id="customerCity" placeholder="Password" name="city" [(ngModel)]="customer && customer.BillAddr.City" >
</div><div class="form-group">
    <label for="customerLine1">State/Province</label>
    <input type="text" class="form-control" id="cutomerLine1" placeholder="Password" name="Province" [(ngModel)]="customer && customer.BillAddr.CountrySubDivisionCode" >
</div>
<div class="form-group">
    <label for="customerLine1">Postal Code</label>
    <input type="text" class="form-control" id="cutomerLine1" placeholder="Password" name="postcode" [(ngModel)]="customer && customer.BillAddr.PostalCode" >
</div>
</div>
</div>
<button type="submit" class="btn btn-default">Save Changes</button>
</form>

The current details are fetched oninit with this function: 当前的详细信息通过此函数在oninit中获取:

getCustomer(id): void {
    this.busy = this.customersService.getCustomer(id)
          .then(customer => this.customer = customer);

  }

First problem is that data is coming async, so customer will be undefined when the view is rendered on all fields. 第一个问题是数据将异步传输,因此在所有字段上呈现视图时都将无法undefined customer Second problem is indeed that, since some fields do not have a value, will also throw an error. 第二个问题确实是,由于某些字段没有值,因此也会引发错误。

Usually this could be solved by just initializing the customer : 通常,这可以通过初始化customer来解决:

customer = {};

But here again the problem is, that you have some deeper property paths that will though throw error despite this, like: customer.BillAddr.Line3 . 但是这里的问题仍然是,您有一些更深的属性路径,尽管如此,它们仍然会引发错误,例如: customer.BillAddr.Line3 Of course you could initialize aaaall properties you have in your object, but that seems just ugly to me. 当然,您可以初始化对象中具有的所有特性,但这对我来说似乎很丑。

All this can be solved with the safe navigation operator . 所有这些都可以通过安全的导航操作员解决。 Unfortunately two-way-binding, ie [(ngModel)] does not allow the safe navigation operator. 不幸的是,双向绑定,即[(ngModel)]不允许安全的导航操作员。

But! 但!

[(ngModel)]="something" equals the following: [(ngModel)]="something"等于以下内容:

[ngModel]="something" (ngModelChange)="changeHappened($event)"

and one-way-binding does support the safe navigation operator. 单向绑定确实支持安全导航操作员。 So what you could then do, is to use the ternary operator, that catches the input user makes and assigns it to your variable (in this example) with customer.Title = $event . 因此,您可以做的是使用三元运算符,该运算符捕获用户输入的内容,并将其分配给具有customer.Title = $event变量(在此示例中)。 And by using the ternary operator you get rid of the error undefined if there is no value initially with applying an empty string to the field: 通过使用三元运算符,您可以消除undefined的错误(如果最初没有值,则将空字符串应用于字段):

[ngModel]="customer?.Title" 
(ngModelChange)="customer?.Title ? customer.Title = $event : ''"

(All credit goes to this answer: https://stackoverflow.com/a/36016472/6294072 ) (所有功劳都归功于这个答案: https : //stackoverflow.com/a/36016472/6294072

Also I could suggest to use a model-driven form here where you could set all fields as empty initially and then just set values to the fields that have value and get rid of the ngModel. 我也建议在这里使用模型驱动的形式,在该形式中,您可以将所有字段初始设置为空,然后将值设置为具有值的字段并摆脱ngModel。 Just to throw in a second option. 只是抛出第二种选择。

But all in all, the above solution should get rid of your errors! 但总而言之,上述解决方案应该摆脱您的错误! :) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM