• 1000 на страницу выхода.
В некоторых компонентах у меня есть форма, и когда пользователь не сохранил изменения, есть canDeactive guard с модальным всплывающим окном, предупреждающим пользователя о несохраненных изменениях. Проблема в том, что теперь, когда сеанс недействителен, срабатывает охрана (поскольку приложение angular еще не знает о недопустимом сеансе), и я застрял во всплывающем окне. Моей целью было бы проверить, действителен ли сеанс, до того, как охранник будет уволен (или оценить в самом охраннике, если сеанс действителен). Моя идея заключалась в том, чтобы вызвать функцию isAuthenticated в бэкэнде, а в охраннике перейти к выходу из системы, на 401 и еще показать диалоговое окно, но поскольку вызов является асинхронным c, он не сработает, и я не понял, как сделай это.
component.ts
createChangeGuard() {
setTimeout(() => {
this.myObjectOrig$ = new BehaviorSubject(this.bookingForm.value).asObservable();
this.isDirty$ = this.bookingForm.valueChanges.pipe(dirtyCheck(this.myObjectOrig$));
this.myObjectOrig$.pipe(untilDestroyed(this)).subscribe(state => { this.bookingForm.patchValue(state, { emitEvent: false }); });
}, 1000);
}
компонент грязной проверки
export interface DirtyComponent {
isDirty$: Observable<boolean>;
// isPrinting: boolean;
hasValidSession$: Observable<boolean>;
}
export function dirtyCheck<U>( source: Observable<U> ) {
let subscription: Subscription;
let isDirty = false;
return function <T>( valueChanges: Observable<T> ): Observable<boolean> {
const isDirty$ = combineLatest(
[source,
valueChanges]
).pipe(
debounceTime(300),
map(( [a, b] ) => { return isDirty = isEqual(a, b) === false;
}),
finalize(() => subscription.unsubscribe()),
startWith(false),
shareReplay({ bufferSize: 1, refCount: true }),
);
subscription = fromEvent(window, 'beforeunload').subscribe(event => {
isDirty && (event.returnValue = false) && event.preventDefault();
});
return isDirty$;
};
}
деактивировать Охранник
export class DirtyCheckGuard implements CanDeactivate<DirtyComponent> {
....
constructor( private modalService: NzModalService,
.....
) {
}
contentNormal = 'Die Änderungen wurden nicht gespeichert. Wollen Sie wirklich die Seite verlassen?';
contentPrint = 'Die Änderungen wurden noch nicht gespeichert. Trotzdem drucken?';
canDeactivate( component: DirtyComponent, currentRoute: ActivatedRouteSnapshot ): Observable<boolean> | boolean {
let formIsDirty = false;
...some logic to set formIsDirty...
return component.isDirty$.pipe(switchMap(dirty => {
let navigate;
if ( (dirty === false && !formIsDirty ) ) {
// update status to status before the booking went into edit mode since no change was made
this.checkPage(currentRoute.data.origin);
return of(true);
} else if (dirty === true || (dirty === false && formIsDirty)) {
return this.modalService.create({
nzTitle: 'Not saved',
nzContent: content,
nzFooter: [
{
label: 'Abbrechen',
onClick: () => {navigate = false; this.modalService.closeAll(); }
},
{
label: confirmText,
type: 'primary',
onClick: () => { navigate = true; this.checkPage(currentRoute.data.origin); this.modalService.closeAll(); }
}
]
}).afterClose.pipe(map(() => navigate ));
}}), take(1));
}
}
перехватчик
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const requestRoute = this.router.url;
return next.handle(request).pipe(retry(1), catchError((error: HttpErrorResponse) => {
// this.errorCount = true;|| this.authenticationService.isLoggedIn() === false
if (error.status === 401 ) {
this.authenticationService.logout(requestRoute);
}
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', error.error.message);
} else {
console.error('An error occurred:', error);
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
if (error.error !== null){
this.showErrorNotification(error.status, error.error?.errorCode, error.error?.errorText);
console.error(`Backend returned code ${error.status}, body was: ${error.error?.errorText}}`);
}
}
return throwError(error.error);
})
);
служба аутентификации
async isAuthenticated(){
const serverUrl = this.baseURL + 'isValidSession';
const response = await this.http.get(serverUrl, httpOptions).toPromise();
return response.toString();
}