Issue
Edit: From what i've understood reading over and over, the issue is that i can't access the properties from currentPerson. And this is where all errors come from. But i compared to other component file and they were almost the same.
First of all, i've checked the links when typing my question title. While the error code is the same, unfortunately i wasn't able to find an proper answer.
I'm totally new to angular\typescript, and i've been following a tutorial i've found on this link: https://www.techiediaries.com/angular-11-crud-rest-api-tutorial/
In order to understand how things works, i've changed product to person (and added more details like surname, address, etc). Everything was going fine, until i've got the part of updating a person details.
When i reached that point (editing person-details-components.ts), when i try to change the method 'updatePerson(): void {}' i'm having the error:
Object is possibly null . ts(2531).
I've tried turning off strictNullCheck on tsconfig.app.json , nothing changed. I've also tried to add the ? operator on the line showing the error, didn't worked also (the error changes, property doesn't exist on type 'never').
Since i'm new to angular, i'm only following the tutorial and trying to undersatnd where the error comes from. I noticed i can access currentperson, but none of its properties (name, address, etc).
I've also compared it to other component.ts files, and there i was able to access the properties i mentioned. What am i doing wrong? And sorry for the bad english.
Thanks.
Heres my 'person-details-components.ts' file:
import { Component, OnInit } from '@angular/core';
import { PersonService } from 'src/app/services/person.service';
import { ActivatedRoute, Router } from '@angular/router';
@Component({
selector: 'app-person-details',
templateUrl: './person-details.component.html',
styleUrls: ['./person-details.component.css']
})
export class PersonDetailsComponent implements OnInit {
currentperson = null;
message = '';
constructor(
private personService: PersonService,
private route: ActivatedRoute,
private router: Router) { }
ngOnInit(): void {
this.message = '';
this.getPerson(this.route.snapshot.paramMap.get('id'));
}
getPerson(id: any): void {
this.personService.read(id)
.subscribe(
person => {
this.currentperson = person;
console.log(person);
},
error => {
console.log(error);
});
}
//All errors start here. I can't access this.currentperson.name and so on
setAvailableStatus(status: any): void {
const data = {
name: this.currentperson.name,
description: this.currentperson.description,
available: status
};
this.personService.update(this.currentperson.id, data)
.subscribe(
response => {
this.currentProduct.available = status;
console.log(response);
},
error => {
console.log(error);
});
}
updateProduct(): void {
this.productService.update(this.currentProduct.id, this.currentProduct)
.subscribe(
response => {
console.log(response);
this.message = 'The product was updated!';
},
error => {
console.log(error);
});
}
deleteProduct(): void {
this.productService.delete(this.currentProduct.id)
.subscribe(
response => {
console.log(response);
this.router.navigate(['/products']);
},
error => {
console.log(error);
});
}
}
Solution
You should always use type
or interface
for your model. In this case, we create the Person
type with id
, name
, and description
.
person.service.ts:
//... other import stuff
export type Person = {
readonly id: number;
readonly name: string;
readonly description: string;
};
@Injectable({
providedIn: 'root'
})
export class PersonService {
//...
}
Then you can import that Person
type and use it. Notice that we use a question mark ?
next to the private _currentperson?
. This tells the compiler that _currentperson
is undefined
. In other words, it is not set (initialized).
Then whenever you want to access this._currentperson
, you always need to check if it's not undefined
. In this case, we do it in setAvailableStatus
function.
It's a good habit to avoid using any
type. We use TypeScript because it enables us to use type system. Using any
defeats that purpose. In short, avoid any
at all cost. You will need it only when you have to deal with low level advanced stuff.
person-details.component.ts
import { Component, OnInit } from '@angular/core';
import { PersonService, Person } from 'src/app/services/person.service';
import { ActivatedRoute, Router } from '@angular/router';
@Component({
selector: 'app-person-details',
templateUrl: './person-details.component.html',
styleUrls: ['./person-details.component.css']
})
export class PersonDetailsComponent implements OnInit {
private _currentperson?: Person;
message = '';
public get currentPerson() {
return this._currentPerson;
}
constructor(
private personService: PersonService,
private route: ActivatedRoute,
private router: Router) { }
ngOnInit(): void {
//...
}
getPerson(id: number): void {
this.personService.read(id)
.subscribe(
//...
);
}
setAvailableStatus(status: boolean): void {
if(this._currentperson === undefined)
throw error('Person does not exist');
const data = {
name: this.currentperson.name,
description: this.currentperson.description,
available: status
};
this.personService.update(this.currentperson.id, data)
.subscribe(
//...
);
}
// ...
}
It's best to show some sort of error message in the HTML when the id
doesn't exist and hide the page. It's not productive to show the page and buttons when the consumers can't even use it.
person-details.component.html
<div *ngIf="currentperson">
<!-- Show person detail stuff -->
</div>
<div *ngIf="!currentperson">
<!-- Show error message or something here because id is invalid -->
</div>
Answered By - skouch2022
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.