Reputation: 679
In my application when I click on a button I would like to display a spinner.
I get a simple CSS spinner from this url : https://projects.lukehaas.me/css-loaders/
I added css to my main.css
file, and after that I've added this line of code in my
app.component.html
:
<div class="loader">Loading...</div>
The reason why I choosed app.component.html
is that I would like to make this spinner available everywhere in my application..
But for now on button click I'm getting list of persons from database. And this is how it looks (my component):
export class PersonComponent implements OnInit {
private modalId: string;
private persons: Array<Person>;
constructor(private personsService: PersonsService) {}
ngOnInit() {}
// Here I'm getting data from database and I would like to display spinner/loader until all of data is loaded
show() {
$('#' + this.modalId).modal('show');
this.personsService.getAll().do(data=>console.log(data)).subscribe(persons => this.persons = persons);
}
}
Here is my app.component.html
<router-outlet></router-outlet>
<div class="loader">Loading...</div>
And here is my PersonsService.ts
which is responsible for fetching data from database:
@Injectable()
export class PersonsService {
public showSpinner: boolean = false;
constructor(private _http: HttpClient) { }
getAll(): Observable<Person[]> {
this.showSpinner(); //Cannot invoke expression whose type lacks a call signature. -> I got this error here
return this._http.get<Person[]>(apiUrl)
.catch(
(error: HttpErrorResponse) => {
return Observable.throw(error);
});
// Somewhere here I would hide a spinner? Is this possible, I mean will this be shown when data is fully loaded or ?
}
displaySpinner() {
this.showSpinner = true;
}
hideSpinner() {
this.showSpinner = false;
}
I need some if condition probably in my app.component.html so it might looks like this? :
<div *ngIf="personsService.showSpinner" class="loader">
Loading...
</div>
Or I need to do something like this? :
<div *ngIf="personsService.showSpinner">
<div class="loader">Loading...</div>
</div>
However this is not working now and I don't know how to achieve this, to simply show spinner when service is getting data from database, and to hide it when all of the data is fetched..
Thanks guys
Cheers
Upvotes: 0
Views: 824
Reputation: 3166
Modify your service to use a BehaviorSubject
instead of a plain boolean
and take advantage of the rxjs pipe
and tap
operator so that you can set the spinner flag in the service itself, instead of toggling in every service consumer component.
@Injectable()
export class PersonsService {
public showSpinner: BehaviorSubject<boolean> = new BehaviorSubject(false);
public readonly apiUrl = "https://api.github.com/users";
constructor(private _http: HttpClient) { }
getAll(): Observable<Person[]> {
this.showSpinner.next(true);
return this._http.get<Person[]>(this.apiUrl).pipe(
tap(response => this.showSpinner.next(false),
(error: any) => this.showSpinner.next(false))
);
}
}
You can use the async
pipe to access showSpinner
<div class="loader" *ngIf="_personService.showSpinner | async">
</div>
<div *ngIf="!(_personService.showSpinner | async)">
<button (click)="foo()">Click here</button>
<pre>
{{response | json}}
</pre>
</div>
Upvotes: 0
Reputation: 27303
You can show hide and know the data base loading success and reading Full response using angular observe option
getAll(): Observable<HttpResponse<Person[]> {
return this._http.get<Person[]>(apiUrl,{ observe: 'events' })
.catch(
(error: HttpErrorResponse) => {
return Observable.throw(error);
});
// Somewhere here I would hide a spinner? Is this possible, I mean will this be shown when data is fully loaded or ?
}
You can set the spinner on service or you can change the status of spinner inside components where you subscribe the getAll() observable example
components.ts
this.service.getAll().subscribe((response:HttpEvent<Object>)=>{
//console.log(response);
//import the HttpEventType from @angular/common/http
if(response.type==HttpEventType.DownloadProgress){
this.showSpinner = true;
}
if(response.type==HttpEventType.Response){
this.showSpinner = true;
}
})
Upvotes: 1