Reputation: 121809
I'm new to Angular and "reactive programming".
I have an Angular 8 component (test-api.component.*) that uses a service (contacts.service.ts) to talk to a REST back-end. It looks like this:
test-api.component.ts:
import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { Contact } from '../models/contact';
import { ContactsService } from '../services/contacts.service';
@Component({
selector: 'app-test-api',
templateUrl: './test-api.component.html',
styleUrls: ['./test-api.component.css']
})
export class TestAPIComponent implements OnInit {
// "$" convention denotes this as an "Observable"
contacts$: Observable<Contact[]>;
constructor(private contactsService: ContactsService) { }
ngOnInit() {
this.loadContacts();
}
loadContacts() {
this.contacts$ = this.contactsService.getContacts();
}
}
test-api-component.html:
<h1>Contacts</h1>
<p *ngIf="!(contacts$ | async)"><em>Loading...</em></p>
<table class="table table-sm table-hover" *ngIf="(contacts$ | async)?.length > 0">
<thead>
<tr>
<th>ContactId</th>
<th>Name</th>
<th>EMail</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let contact of (contacts$ | async)">
<td>{{ contact.ContactId }}</td>
<td>{{ contact.Name }}</td>
<td>{{ contact.EMail }}</td>
</tr>
</tbody>
</table>
I'm developing with Visual Studio code.
How/where can I set a breakpoint in my code so I can see my contacts[]
array in the debugger after the async operation has completed? I just want to be able to look at individual "contact" elements in the debugger.
I know how to set breakpoints and use JS debuggers (both VSCode/Chrome extensions and Chrome Developer Tools), but I didn't know how best to modify the code so that I could examine the data that was otherwise going straight into the HTML template.
Andrei Gătej gave the most detailed answer to my implicit questions (what exactly is happening "under the covers" when I declare an "Observable" or pipe "async"?)
Both Mustafa Kunwa and Himanshu Singh gave me effectively the SAME answer - the one that I went with.
Anyway, my final code looks like this:
test-api.component.html
<tr *ngFor="let contact of (contactsList)">
<td>{{ contact.contactId }}</td>
<td>{{ contact.name }}</td>
<td>{{ contact.eMail }}</td>
...
test-api.component.ts
export class TestAPIComponent implements OnInit, OnDestroy {
contactsList: Contact[];
private contactsSubscription$: Subscription;
...
ngOnInit() {
this.contactsSubscription$ =
this.contactsService.getContacts().subscribe(
data => {
this.contactsList = data;
console.log('loadContacts', data);
},
err => {
console.error('loadContacts', err);
});
...
ngOnDestroy() {
this.contactsSubscription$.unsubscribe();
}
Upvotes: 3
Views: 3213
Reputation: 11979
Note that in your template you are applying the async pipe twice to your observable, which will create 2 subscribers.
Although the async pipe takes care of unsubscribing from your observable, having multiple subscriptions might be redundant.
To solve this, you can wrap your part of the template which will make use of that observable(contacts$
) with an ng-container
, so that only one subscription will be created
<ng-container *ngIf="(contacts$ | async) as contacts; else loading">
<h1>Contacts</h1>
<table class="table table-sm table-hover" *ngIf="contacts.length > 0">
<thead>
<tr>
<th>ContactId</th>
<th>Name</th>
<th>EMail</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let contact of (contacts$ | async)">
<td>{{ contact.ContactId }}</td>
<td>{{ contact.Name }}</td>
<td>{{ contact.EMail }}</td>
</tr>
</tbody>
</table>
<p *ngIf="contacts.length === 0">No contacts!</p>
</ng-container>
<ng-template #loading>
<p>
<em>Loading...</em>
</p>
</ng-template>
Regarding your question, I find Nicholas' first comment helpful.
Besides the debugger, here is my preferred approach:
loadContacts() {
this.contacts$ = this.contactsService.getContacts().pipe(tap(console.log));
}
Upvotes: 1
Reputation: 867
try this
this.contactsService.getContacts().subscribe(
res=>{
console.log(res);
},
err=>{
console.log(err);
});
Upvotes: 2
Reputation: 2165
Instead of calling loadContacts()
from ngOnInit(). You can directly fetch data from API in ngOnInit()
only. Then on the mentioned line in code you can add debug
point to see the data received from the API
ngOnInit() {
this.contactsService.getContacts().subscribe((data)=>{
console.log(data); // <---- here you can add debug point
})
}
Upvotes: 2