Skip to content

Commit

Permalink
Warning when leaving page
Browse files Browse the repository at this point in the history
  • Loading branch information
Samonella7 committed Nov 18, 2019
1 parent 0517521 commit 25d652a
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 3 deletions.
4 changes: 3 additions & 1 deletion SBOLCanvasFrontend/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { PendingChangesGuard} from './pending-changes.guard';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

import { HomeComponent } from './home/home.component';

const routes: Routes = [
{path: '', component: HomeComponent},
{path: 'home', component: HomeComponent}
{path: 'home', component: HomeComponent},
{ path: '', component: HomeComponent, canDeactivate: [PendingChangesGuard] },
];

@NgModule({
Expand Down
5 changes: 4 additions & 1 deletion SBOLCanvasFrontend/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import { AppRoutingModule } from './app-routing.module';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { AppHttpInterceptor } from './http.interceptor';

// for warning against leaving the page with unsaved changes
import { PendingChangesGuard} from './pending-changes.guard';

// Angular Material stuff. This is a different UI library than ng-bootstrap.
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import { MaterialModule } from './material.module';
Expand Down Expand Up @@ -69,7 +72,7 @@ import { ExportComponent } from './export/export.component';
ReactiveFormsModule,
MaterialModule
],
providers: [GraphService, MetadataService, {
providers: [PendingChangesGuard, GraphService, MetadataService, {
provide: HTTP_INTERCEPTORS, useClass: AppHttpInterceptor, multi: true
}],
bootstrap: [AppComponent],
Expand Down
13 changes: 12 additions & 1 deletion SBOLCanvasFrontend/src/app/home/home.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import {Component, HostListener, OnInit, ViewChild} from '@angular/core';
import {GlyphInfo} from '../glyphInfo';
import {GraphService} from "../graph.service";
import { ToolbarComponent } from "../toolbar/toolbar.component";
import {ComponentCanDeactivate} from '../pending-changes.guard';
import {Observable} from 'rxjs';

export enum KEY_CODE {
DELETE = "Delete",
Expand All @@ -15,7 +17,7 @@ export enum KEY_CODE {
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
export class HomeComponent implements OnInit, ComponentCanDeactivate {

@ViewChild(ToolbarComponent) toolbar

Expand Down Expand Up @@ -65,4 +67,13 @@ export class HomeComponent implements OnInit {
}
}
}

// @HostListener allows us to also guard against browser refresh, close, etc.
@HostListener('window:beforeunload')
canDeactivate(): Observable<boolean> | boolean {
// insert logic to check if there are pending changes here;
// returning true will navigate without confirmation
// returning false will show a confirm dialog before navigating away
return false;
}
}
15 changes: 15 additions & 0 deletions SBOLCanvasFrontend/src/app/pending-changes.guard.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { TestBed, async, inject } from '@angular/core/testing';

import { PendingChangesGuard } from './pending-changes.guard';

describe('PendingChangesGuard', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [PendingChangesGuard]
});
});

it('should ...', inject([PendingChangesGuard], (guard: PendingChangesGuard) => {
expect(guard).toBeTruthy();
}));
});
20 changes: 20 additions & 0 deletions SBOLCanvasFrontend/src/app/pending-changes.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { CanDeactivate } from '@angular/router';
import { Injectable } from '@angular/core';
import {Observable} from 'rxjs';

export interface ComponentCanDeactivate {
canDeactivate: () => boolean | Observable<boolean>;
}

@Injectable()
export class PendingChangesGuard implements CanDeactivate<ComponentCanDeactivate> {
canDeactivate(component: ComponentCanDeactivate): boolean | Observable<boolean> {
// if there are no pending changes, just allow deactivation; else confirm first
return component.canDeactivate() ?
true :
// NOTE: this warning message will only be shown when navigating elsewhere within your angular app;
// when navigating away from your angular app, the browser will show a generic warning message
// see http://stackoverflow.com/a/42207299/7307355
confirm('WARNING: You have unsaved changes. Press Cancel to go back and save these changes, or OK to lose these changes.');
}
}

0 comments on commit 25d652a

Please sign in to comment.