Reputation: 23
I am trying to get data(JSON) from the server and display on the web only after I click on the button. After the first click, I get an error:
core.js:4352 ERROR TypeError: Cannot read property 'imie' of undefined
at HttpTestComponent.get (http-test.component.ts:28)
at HttpTestComponent_Template_button_click_6_listener (http-test.component.html:6)
at executeListenerWithErrorHandling (core.js:15214)
at wrapListenerIn_markDirtyAndPreventDefault (core.js:15249)
at HTMLButtonElement.<anonymous> (platform-browser.js:582)
at ZoneDelegate.invokeTask (zone-evergreen.js:399)
at Object.onInvokeTask (core.js:27474)
at ZoneDelegate.invokeTask (zone-evergreen.js:398)
at Zone.runTask (zone-evergreen.js:167)
at ZoneTask.invokeTask [as invoke] (zone-evergreen.js:480)
After the Second click it's works. Where is the problem?
service file
export class LoginService {
private url = 'http://localhost:8080/test';
constructor(private http:HttpClient) {
}
getTest(): Observable<IPerson>{
return this.http.get<IPerson>(this.url);
}
}
component file
export class HttpTestComponent implements OnInit{
private record:IPerson;
name: string="aaaa";
surname: string="bbbb";
constructor(private loginService: LoginService) { }
get(){
this.loginService.getTest().subscribe((data:IPerson)=>this.record = data);
this.name = this.record.imie;
this.surname = this.record.nazwisko;
}
ngOnInit(): void {
}
}
IPerson class
export class IPerson implements Person{
_imie: string;
_nazwisko: string;
get imie(): string {
return this._imie;
}
get nazwisko(): string {
return this._nazwisko;
}
}
template
<p>http-test works!</p>
<h1>{{name}}</h1>
<h1>{{surname}}</h1>
<button class="btn-large" (click)="get()">Dane</button>
Upvotes: 0
Views: 950
Reputation: 17858
The issue is in this line;
this.loginService.getTest().subscribe((data:IPerson)=>this.record = data);
Now, .subscribe
is a method of Observable type, and quoting here;
Observables are declarative—that is, you define a function for publishing values, but it is not executed until a consumer subscribes to it. The subscribed consumer then receives notifications until the function completes, or until they unsubscribe.
Based on your code, it seems that your Observable is to perform http GET request on user
.
Now, moving to the next line;
this.name = this.record.imie;
This is the code that throws the error, because when this line gets executed this.record
is still undefined
since you assign this.record
in the observable callback.
One of the approach is to wrap the code after observable runs your callback;
this.loginService.getTest().subscribe((data:IPerson) =>
this.record = data;
this.name = this.record.imie;
this.surname = this.record.nazwisko;
);
Other approach is to encapsulate your function with async/await
, based on your code - perhaps it would be like (Following code is not tested);
// In your service
getTest() : Promise<any> {
const response = this.http.get(this.url).toPromise();
return response.json(); // Not sure if this is needed.
}
// Component
async getUser() {
const record = await this.loginService.getTest();
this.name = record.imie;
this.surname = record.nazwisko;
}
Upvotes: 1
Reputation: 3593
This is because getTest() is async, you need to fetch props inside subscriber, otherwise record is undefined
get(){
this.loginService.getTest().subscribe((data:IPerson)=> {
this.record = data;
this.name = this.record.imie;
this.surname = this.record.nazwisko;
});
}
Upvotes: 1