Reputation: 2647
In my Angular-12 I have this code:
And your JSON is invalid. It should be as below:
{
"message": "Employee Detail.",
"error": false,
"code": 200,
"results": {
"employee": {
"id": 8,
"first_name": "JONAH",
"last_name": "YAKUBU",
"other_name": "STANLEY",
"licences": [
{
"id": 1,
"licence_number": "dsdsdsd"
}
]
}
}
}
interface:
export class EmployeeResponse {
results!: { employee: IEmployee };
}
export interface IEmployee {
id?: number;
first_name: string;
other_name: string;
last_name: string;
licence_number?: string;
licences?: ILicence[];
}
export interface ILicence {
id: number;
licence_number: string;
dl_classification_id: number;
licenceclass?: {id:number,class_name:string};
}
service:
getEmployeeById(id: number): Observable<EmployeeResponse> {
return this.http.get('/assets/data.json').pipe(
map((response: any) => {
if (!response) return response;
if (!response.results) return response;
if (!response.results.employee) return response;
let employee: IEmployee = {
...response.results.employee,
licence_number:
response.results.employee.licences &&
response.results.employee.licences[0].licence_number
};
response.results.employee = employee;
return response;
})
);
}
component:
export class AppComponent {
profileInfoForm!: FormGroup;
licenceInfoForm!: FormGroup;
profileTemplate: boolean = true;
licenceTemplate: boolean = false;
isLoading = false;
employee: IEmployee;
_id = 1;
constructor(
private fb: FormBuilder,
private employeeService: EmployeeService
) {}
ngOnInit(): void {
this.isLoading = true;
//this._id = this.route.snapshot.params['id'];
this.updateEmployee();
this.updateLicence();
this.loadEmployeeById();
}
profileFunction() {
this.profileTemplate = true;
this.licenceTemplate = false;
}
licenceFunction() {
this.profileTemplate = false;
this.licenceTemplate = true;
}
updateEmployee() {
this.profileInfoForm = this.fb.group({
id: [''],
first_name: [
'', [Validators.required, Validators.minLength(2), Validators.maxLength(50)]
],
other_name: ['', [Validators.maxLength(50)]],
last_name: [
'', [Validators.required, Validators.minLength(2), Validators.maxLength(50)]
]
});
}
updateLicence() {
this.licenceInfoForm = this.fb.group({
id: [''],
licence_number: ['', [Validators.required, Validators.minLength(2)]]
});
}
get fp() {
return this.profileInfoForm.controls;
}
get fl() {
return this.licenceInfoForm.controls;
}
profileValidate() {
if (!this.profileInfoForm.valid) {
this.profileInfoForm.markAllAsTouched();
return;
}
}
licenceValidate() {
if (!this.licenceInfoForm.valid) {
this.licenceInfoForm.markAllAsTouched();
return;
}
}
loadEmployeeById() {
this.employeeService
.getEmployeeById(this._id)
.subscribe((data: EmployeeResponse) => {
console.log(data.results.employee)
this.employee = data.results.employee;
this.profileInfoForm.patchValue({
first_name: this.employee.first_name,
other_name: this.employee.other_name,
last_name: this.employee.last_name
});
this.licenceInfoForm.patchValue({
licence_number: this.employee.licence_number
});
});
}
}
<div class="col-md-3">
<div class="sticky-top mb-3">
<div class="card">
<div class="card-header">
<h4 class="card-title">Click to Edit</h4>
</div>
<div class="card-body">
<div id="external-events">
<button (click)="profileFunction()" type="button" class="btn btn-block btn-primary">Profile</button>
<button (click)="licenceFunction()" type="button" class="btn btn-block btn-warning">Licence</button>
</div>
</div>
<div class="card-header">
</div>
</div>
</div>
</div>
<div class="col-md-9" *ngIf="employee != undefined">
<div *ngIf="profileTemplate" class="card card-default color-palette-box">
<div class="card-body">
<form [formGroup]="profileInfoForm" (ngSubmit)="onSubmitProfile()">
<div class="row">
<div class="col-md-12">
<div class="row">
<div class="col-12 col-md-4">
<div class="form-group">
<label for="first_name">First Name:<span style="color:red;">*</span></label>
<input type="text" formControlName="first_name" placeholder="First Name" class="form-control" required/>
</div>
<div *ngIf="fp.first_name.touched && fp.first_name.invalid">
<div *ngIf="fp.first_name.hasError('required')">
<div class="text-danger">
First Name is required!
</div>
</div>
<div *ngIf="fp.first_name.hasError('minlength')">
<div class="text-danger">
First Name cannot be less than 2 characters!
</div>
</div>
<div *ngIf="fp.first_name.hasError('maxlength')">
<div class="text-danger">
First Name cannot be more than 50 characters!
</div>
</div>
</div>
</div>
<div class="col-12 col-md-4">
<div class="form-group">
<label for="other_name">Middle Name:<span style="color:red;">*</span></label>
<input type="text" formControlName="other_name" placeholder="Middle Name" class="form-control" required/>
</div>
<div *ngIf="fp.other_name.touched && fp.other_name.invalid">
<div *ngIf="fp.other_name.hasError('maxlength')">
<div class="text-danger">
Middle Name cannot be more than 50 characters!
</div>
</div>
</div>
</div>
<div class="col-12 col-md-4">
<div class="form-group">
<label for="last_name">Last Name:<span style="color:red;">*</span></label>
<input type="text" formControlName="last_name" placeholder="Last Name" class="form-control" required/>
</div>
<div *ngIf="fp.last_name.touched && fp.last_name.invalid">
<div *ngIf="fp.last_name.hasError('required')">
<div class="text-danger">
Last Name is required!
</div>
</div>
<div *ngIf="fp.last_name.hasError('minlength')">
<div class="text-danger">
Last Name cannot be less than 2 characters!
</div>
</div>
<div *ngIf="fp.last_name.hasError('maxlength')">
<div class="text-danger">
Last Name cannot be more than 50 characters!
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="card-footer">
<button type="submit" class="btn btn-success" [disabled]="isLoading" class="btn btn-success" (click)="profileValidate()">
<span *ngIf="isLoading" class="spinner-border spinner-border-sm mr-1"></span>
<i class="fa fa-save" aria-hidden="true"></i> Save</button>
</div>
</form>
</div>
</div>
<div *ngIf="licenceTemplate" class="card card-default color-palette-box">
<form [formGroup]="licenceInfoForm" (ngSubmit)="onSubmitLicence()">
<div class="row">
<div class="col-12 col-md-6">
<div class="form-group">
<label for="licence_number">Licence Number:<span style="color:red;">*</span></label>
<input type="text" formControlName="licence_number" placeholder="Licence Number" class="form-control" required/>
</div>
<div *ngIf="fl.licence_number.touched && fl.licence_number.invalid">
<div *ngIf="fl.licence_number.hasError('required')">
<div class="text-danger">
Licence Number is required!
</div>
</div>
<div *ngIf="fl.licence_number.hasError('minlength')">
<div class="text-danger">
Licence Number cannot be less than 2 characters!
</div>
</div>
<div *ngIf="fl.licence_number.hasError('maxlength')">
<div class="text-danger">
Licence Number cannot be more than 50 characters!
</div>
</div>
</div>
</div>
<div class="card-footer">
<button type="submit" class="btn btn-success" [disabled]="isLoading" class="btn btn-success" (click)="licenceValidate()">
<span *ngIf="isLoading" class="spinner-border spinner-border-sm mr-1"></span>
<i class="fa fa-save" aria-hidden="true"></i> Save</button>
</div>
</div>
</form>
</div>
</div>
Initially, everything was working fine but suddenly, I got this error:
ERROR TypeError: Cannot read properties of undefined (reading 'licence_number')
which is coming from the service.
How do I resolve this?
Thanks.
ERROR TypeError: Cannot read properties of undefined (reading 'licence_number')
Upvotes: 4
Views: 94048
Reputation: 59
if you are checking like ngIf="someArray[0]?
then you should initialize your array on your component like this: someArray: any[] = []
if you just declare someArray: any[]
it will give the error
Upvotes: 1
Reputation: 19173
let employee: IEmployee = {
...response.results.employee,
licence_number:
(response.results.employee.licences &&
response.results.employee.licences[0] &&
response.results.employee.licences[0].licence_number )
? response.results.employee.licences[0].licence_number : '';
Try to check better if the field is there and if not then provide an empty string ''
Here is a simple example why your checks are not enough.
const c = {d: []}
console.log(c.d); // -> prints []
console.log(c.d[0]); // -> prints undefined
You can also understand that is important to always patch the value with something. So if in the end the value you try to patch is undefined
, it will fail. In that case you must first check and if undefined
then patch it with an empty string ''
.
Upvotes: 3
Reputation: 786
I think or you read the wrong JSON or enter in one of this case...
if (!response) return response;
if (!response.results) return response;
if (!response.results.employee) return response;
Try to change this code into this
if (!response) return response;
if (!response['results']) return response;
if (!response['results']['employee']) return response;
Upvotes: 1