Reputation: 75
I am getting error "Cannot read property 'name' of undefined" I have a simple api that returns a Vehicle, which has these fields
public int Id {get ;set;}
public int ModelId { get; set; }
public KeyValuePairResource Model { get; set; }
public KeyValuePairResource Make { get; set; }
public bool IsRegistered { get; set; }
public Contact ContactInformation { get; set; }
public DateTime LastUpdate {get; set;}
public ICollection<KeyValuePairResource> Features { get; set; }`
Now, In the angular front end, I have a simple get method that calls this api endpoint
getVehicle(id) {
return this.http.get('/api/vehicles/'+ id);
}
in my angular component onInit function i am doing
ngOnInit() {
this.makes = this.vehicleService.getMakes();
this.features = this.vehicleService.getFeatures();
// this.vehicle is defined as any
this.vehicleService.getVehicle(this.vehicle.id)
.subscribe(res=> { this.vehicle = res ;});
}
and finally the code where the program fails seems to be in the HTML
<div class="form-group"><label for="ContactName">Name</label>
<input id= "ContactName" required #name="ngModel" type="text" class="form-control" [(ngModel)] = "vehicle.ContactInformation.name " name = "name"></div>
<div class="alert alert-danger" *ngIf="!name.valid && name.touched">Please enter Name</div>
I have seen similar problems on stack, but none of them have actually solved my problem. I know that the function is asynchronous and the webpage tries to load it before the async function returns completely. But i have other parts in the code where i try to access things like in
<div *ngFor="let f of features"class="checkbox">
<label for="feature{{f.id}}" (change) = "onFeatureToggle(f.id , $event)">
<input type="checkbox" id="feature{{f.id}}">{{f.name}}
</label>
and that doesn't seem to crash. I am really confused. I think i have given what is necessary for this problem, but please tell me if i need to provide more code. The worst part is, i actually got it to work by accident, and the code in onInit didn't look any different.
Upvotes: 1
Views: 260
Reputation: 71911
In your component the expression vehicle.ContactInformation.name
is not defined, because ContactInformation
is undefined. This will cause an error in the template.
Because you are using ngModel
with two way binding, you cannot use vehicle.ContactInformation?.name
. You should try to first check if it exists with an *ngIf
:
<input *ngIf="vehicle.ContactInformation"
id="ContactName" required #name="ngModel"
type="text" class="form-control"
[(ngModel)]="vehicle.ContactInformation.name" name="name">
Or you can not use two way binding and split it up:
<input
id="ContactName" required #name="ngModel"
type="text" class="form-control"
[ngModel]="vehicle.ContactInformation?.name"
(ngModelChange)="vehicle.ContactInformation ? vehicle.ContactInformation.name = $event : null"
name="name">
The reason it works with your *ngFor
loop, is because the *ngFor
checks if the passed array is defined, if it's not, it doesn't loop.
You can also try to initialize your object beforehand:
vehicle = {
id: this.route.snapshot.params.id,
features: [],
contactInformation: {}
};
But I think the issue you are having, is that it's contactInformation
and not ContactInformation
. The rest of your code seems to be using lowercase like features
and id
, I don't see why just ContactInformation
is with a capital
Upvotes: 3