I am developing an Angular Application as hobby project and trying to write clean code with best practices.
I created a ".loader" css class and put it on the main div of app-component. My purpose is to attach this class when the BackendService.loading field is true and detach when false. This will create a loading effect for the whole page. I planned to change this BackendService.loading to true when I call an endpoint and to false when response is provided. I crate this BackendService to handle all other services' http calls. So that I don't have to set this variable in every components in every subscription's response callback.
The problem: I can set variable from BackendService when a new api call request came but I could not set it to false again when it is end because it's subscription is done in component controller.
How can I set the loading variable in BackendService to false when the response is provided? (I read too much things about Observable and tried to wrap http.get's return in another observable for example but none of them is worked) Or do I need to implement something else which is more clean?
BackendService:
export class BackendService {
apiUrl = 'http://localhost:8080';
loading = false;
token = null;
constructor(private http: HttpClient) {}
getOptions() {
return {
headers: new HttpHeaders()
.set('Authorization', this.token)
.set('Content-type', 'application/json')
.set('Access-Control-Allow-Origin', '*')
};
}
getRequest(path: string): Observable<any> {
return this.http.get(this.apiUrl + path, this.getOptions());
}
postRequest(path: string, body: Object): Observable<any> {
return this.http.post(this.apiUrl + path, body, this.getOptions());
}
}
Random other service which use BackendService to make api calls:
export class StudentService {
constructor(private backendService: BackendService) {}
updateLevel(studentId: number) {
return this.backendService.getRequest(
'/student/update-level/' + studentId + '/6/turkce/paragraf');
}
getSummary(studentId: number) {
return this.backendService.getRequest(
'/student/summary/' + studentId) as Observable<StudentSummaryModel>;
}
}
An api call inside a component controller: (Here I have to inject BackendService.loading in result callback)
export class QuizStartComponent implements OnInit {
constructor(private router: Router,
private quizService: QuizService,
private studentService: StudentService,
private userService: UserService) { }
ngOnInit() {
}
quizStart(quizSize: number) {
this.quizService.quizSize = quizSize;
this.studentService.updateLevel(this.userService.user.id).subscribe(
res => {
this.router.navigate(['/student/question']);
}, err => {
});
}
}
Not related but these are app.component.ts and loader css class:
<app-navigation></app-navigation>
<div class="container mb-auto" [ngClass]="{'loading': backendService.loading}">
<div class="mt-3">
<router-outlet></router-outlet>
</div>
</div>
<app-footer></app-footer>
.loading {
... some css
}
.loading:after {
... some css
}