最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to handle connection loss page in Angular 7? - Stack Overflow

programmeradmin4浏览0评论

What I want is that, If the network is not available, and the user tries to navigate to the next page ConnectionLost Component would be there.

But if there is no network and user do not take any action means not navigating to the second page. then there should not be a connection-lost page. The user should stay on the current page.

For that, I have implemented canActivate guard as the following code:

@Injectable({
  providedIn: 'root'
})
export class NetworkGuard implements CanActivate {
  constructor(private router: Router, private network: NetworkService) {
  }

  canActivate(next: ActivatedRouteSnapshot,
              state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
    if (window.navigator.onLine) {
      return true;
    } else {
      if (!this.isConnectionLostComponent()) {
        this.router.navigate(['/connection-lost'], {skipLocationChange: true});
      }
      return false;
    }
  }

  private isConnectionLostComponent() {
    // check whether connection lost component is added on not
    return thiswork.isActive;
  }
}

It's working fine except for one condition. That is if I click back or forward from the browser, its update URL connection-lost to the address bar

How could I solve this problem? Can see the sample Here

steps to produce the issue:

  1. Click banner(Button) -> URL change to '/banner'
  2. Click brand(Button) -> URL change to '/brand'
  3. Disconnect network on that brand page
  4. Click back from browser-> ConnectionLostComponent and url is '/brand', that's okay
  5. Click back again -> ConnectionLostComponent but url is also changed to '/connection-lost'. that's what I'm facing the problem.

I just don't want to update the URL with '/connection-lost', for that I added skipLocationChange: true option to router.navigate method in the NetworkGuard, But still it's not working.

What I want is that, If the network is not available, and the user tries to navigate to the next page ConnectionLost Component would be there.

But if there is no network and user do not take any action means not navigating to the second page. then there should not be a connection-lost page. The user should stay on the current page.

For that, I have implemented canActivate guard as the following code:

@Injectable({
  providedIn: 'root'
})
export class NetworkGuard implements CanActivate {
  constructor(private router: Router, private network: NetworkService) {
  }

  canActivate(next: ActivatedRouteSnapshot,
              state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
    if (window.navigator.onLine) {
      return true;
    } else {
      if (!this.isConnectionLostComponent()) {
        this.router.navigate(['/connection-lost'], {skipLocationChange: true});
      }
      return false;
    }
  }

  private isConnectionLostComponent() {
    // check whether connection lost component is added on not
    return this.network.isActive;
  }
}

It's working fine except for one condition. That is if I click back or forward from the browser, its update URL connection-lost to the address bar

How could I solve this problem? Can see the sample Here

steps to produce the issue:

  1. Click banner(Button) -> URL change to '/banner'
  2. Click brand(Button) -> URL change to '/brand'
  3. Disconnect network on that brand page
  4. Click back from browser-> ConnectionLostComponent and url is '/brand', that's okay
  5. Click back again -> ConnectionLostComponent but url is also changed to '/connection-lost'. that's what I'm facing the problem.

I just don't want to update the URL with '/connection-lost', for that I added skipLocationChange: true option to router.navigate method in the NetworkGuard, But still it's not working.

Share Improve this question edited Feb 27, 2019 at 12:10 Ravi Sevta asked Feb 18, 2019 at 15:08 Ravi SevtaRavi Sevta 3,0851 gold badge26 silver badges42 bronze badges 3
  • You could store the last visited URL, and if the users goes back to it, then prevent your condition ? You can't do much else, as the browsers forbid you to know if the user clicked on the back button. – user4676340 Commented Feb 18, 2019 at 15:10
  • developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/onLine – Reactgular Commented Feb 18, 2019 at 15:23
  • @trichetriche I can check last visited URL but how could I prevent user to go back until he/she is online, and I have added a similar type of condition in isConnectionLostComponent() method, please check my updated question. – Ravi Sevta Commented Feb 19, 2019 at 5:17
Add a comment  | 

2 Answers 2

Reset to default 10

I don't know is it the right solution or not for you but what I did in my project is following.

app.component.ts

constructor(){
this.onlineOffline = Observable.merge(of(navigator.onLine),
      fromEvent(window, 'online').pipe(map(() => true)),
      fromEvent(window, 'offline').pipe(map(() => false))
    );
}

app.component.html

<ng-container *ngIf="onlineOffline | async; then thenTemplate; else elseTemplate"></ng-container>
<ng-template #thenTemplate>
 <router-outlet></router-outlet>
</ng-template>
<ng-template #elseTemplate>
  <app-no-network></app-no-network>
</ng-template>

Let me know if it is working the way you need to implement it or not.

After a little bit of search, and with help of @AlokeT's answer. I got a solution to this problem.

@AlokeT's suggestion is showing connection loss page as soon as the user lost his/her network. but my requirement is to show that connection loss page while he/she tries to navigate to another page.

And In this answer, I just added, that missing part.

For that, I just update that isNetworkStopped flag from Guard, and because every CanActivate guard executes before navigation starts. So connection lost component would show while the user changing the path.

There is a code of NetworkService which I'm using in NetworkGuard,

@Injectable({providedIn: 'root'})
export class NetworkService {

  online: boolean;
  isNetworkStopped = false;

  constructor() {
    this.online = window.navigator.onLine;

    fromEvent(window, 'online').subscribe(e => {
      this.online = true;
    });

    fromEvent(window, 'offline').subscribe(e => {
      this.online = false;
    });
  }
}

Here in above code I just added a flag isNetworkStopped. And updated that flag from NetworkGuard, means while the user tries to navigate to next page and found no network.

And also removed navigation from NetworkGuard. See my below, updated code of NetoworkGuard

@Injectable({providedIn: 'root'})
export class NetworkGuard implements CanActivate {
  constructor(private network: NetworkService) {
  }

  canActivate(next: ActivatedRouteSnapshot,
              state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
    if (this.network.online) {
      return true;
    }
    this.network.isNetworkStopped = true;
    return false;
  }
}

And based on that flag I managed to show ConnectionLost component. For that ConnectionLostcomponent is added on condition based to root component's template.

app.component.html

<router-outlet *ngIf="!networkService.isNetworkStopped"></router-outlet>
<app-connection *ngIf="networkService.isNetworkStopped"></app-connection>

And from ConnectionLost component, if the user clicks on the reload button. By checking network connection I updated isNetworkStopped flag of NetworkService.

发布评论

评论列表(0)

  1. 暂无评论