I need to maintain an alert box on the Registration
page indicating the user has registered successfully. However, by redirecting to the Login
form this box disappears, because the page refreshes.
I utilize the Alert
component to manage this scenario. All of the features work flawlessly but this problem really makes me confused. I shared my code and hope you assist me in getting to the root of this predicament.
alert.component.ts
import { Component, OnInit, OnDestroy, Input } from '@angular/core';
import { Router, NavigationStart } from '@angular/router';
import { Subscription } from 'rxjs';
import { Alert, AlertType } from 'src/app/_models/alert';
import { AlertService } from 'src/app/_services/alert.service';
@Component({ selector: 'alert',
templateUrl: 'alert.component.html',
styleUrls: ['./alert.component.scss'] })
export class AlertComponent implements OnInit, OnDestroy {
@Input() id = 'default-alert';
@Input() fade = true;
alerts: Alert[] = [];
alertSubscription: Subscription;
routeSubscription: Subscription;
constructor(private router: Router, private alertService: AlertService) { }
ngOnInit() {
// subscribe to new alert notifications
this.alertSubscription = this.alertService.onAlert(this.id)
.subscribe(alert => {
// clear alerts when an empty alert is received
if (!alert.message) {
// filter out alerts without 'keepAfterRouteChange' flag
this.alerts = this.alerts.filter(x => x.keepAfterRouteChange);
// remove 'keepAfterRouteChange' flag on the rest
this.alerts.forEach(x => delete x.keepAfterRouteChange);
return;
}
// add alert to array
this.alerts.push(alert);
setTimeout(() => this.removeAlert(alert), 5000);
});
// clear alerts on location change
this.routeSubscription = this.router.events.subscribe(event => {
if (event instanceof NavigationStart) {
this.alertService.clear(this.id);
}
});
}
ngOnDestroy() {
// unsubscribe to avoid memory leaks
this.alertSubscription.unsubscribe();
this.routeSubscription.unsubscribe();
}
removeAlert(alert: Alert) {
// check if already removed to prevent error on auto close
if (!this.alerts.includes(alert)) return;
if (this.fade) {
// fade out alert
this.alerts.find(x => x === alert).fade = true;
// remove alert after faded out
setTimeout(() => {
this.alerts = this.alerts.filter(x => x !== alert);
}, 250);
} else {
// remove alert
this.alerts = this.alerts.filter(x => x !== alert);
}
}
cssClass(alert: Alert) {
if (!alert) return;
const classes = ['toast'];
const alertTypeClass = {
[AlertType.Success]: 'toast-success',
[AlertType.Error]: 'toast-error',
[AlertType.Info]: 'toast-info',
[AlertType.Warning]: 'toast-warning'
}
classes.push(alertTypeClass[alert.type]);
if (alert.fade) {
classes.push('fade');
}
return classes.join(' ');
}
}
alert.service.ts
import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { filter } from 'rxjs/operators';
import { Alert, AlertType } from '../_models/alert';
@Injectable({ providedIn: 'root' })
export class AlertService {
private subject = new Subject<Alert>();
private defaultId = 'default-alert';
// enable subscribing to alerts observable
onAlert(id = this.defaultId): Observable<Alert> {
return this.subject.asObservable().pipe(filter(x => x && x.id === id));
}
// convenience methods
success(message: string, options?: any) {
this.alert(new Alert({ ...options, type: AlertType.Success, message }));
}
error(message: string, options?: any) {
this.alert(new Alert({ ...options, type: AlertType.Error, message }));
}
info(message: string, options?: any) {
this.alert(new Alert({ ...options, type: AlertType.Info, message }));
}
warn(message: string, options?: any) {
this.alert(new Alert({ ...options, type: AlertType.Warning, message }));
}
// main alert method
alert(alert: Alert) {
alert.id = alert.id || this.defaultId;
this.subject.next(alert);
}
// clear alerts
clear(id = this.defaultId) {
this.subject.next(new Alert({ id }));
}
}
This is a piece of code in which an alert message is called (It should be noted that the keepAfterRouteChange
is set to True):
onSubmit() {
this.submitted = true;
// reset alerts on submit
this.alertService.clear();
// stop here if form is invalid
if (this.form.invalid) {
return;
}
this.loading = true;
this.accountService
.register(this.form.value)
.pipe(first())
.subscribe((data) => {
this.loading = false;
this.submitted = false;
if (data.hasError) {
this.alertService.error(data.errorMessage);
} else {
this.alertService.success('Registration successfully completed.', {
keepAfterRouteChange: true,
});
localStorage.setItem('regCount',JSON.parse(localStorage.getItem('regCount')) 1);
this.router.navigate(['/login']).then(() => {
window.location.reload();
});
}
},
() => {
this.loading = false;
this.submitted = false;
this.alertService.error('Something went wrong.');
});
}
CodePudding user response:
Your problem probably comes from window.location.reload();
when window is reloaded all components and services are flushed. Find other ways to clear services if that's the point. Or find other way to store info alert should be showing (e.g SessionStorage or LocalStorage) - which doesn't seem like a good idea though.