Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ionic-framework/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 离子5中CanDeactivate guard的导航问题_Angular_Ionic Framework_Routes_Ionic5_Candeactivate - Fatal编程技术网

Angular 离子5中CanDeactivate guard的导航问题

Angular 离子5中CanDeactivate guard的导航问题,angular,ionic-framework,routes,ionic5,candeactivate,Angular,Ionic Framework,Routes,Ionic5,Candeactivate,在我的Ionic 5应用程序中,我有以下导航路径 PageHome -> PageA -> PageB 我已经为PageA实现了CanDeactivate守卫 export class LeavePageGuard implements CanDeactivate<isDeactivatable>{ canDeactivate( component: isDeactivatable ): Observable<boolean> | Prom

在我的Ionic 5应用程序中,我有以下导航路径

PageHome -> PageA ->  PageB
我已经为PageA实现了CanDeactivate守卫

export class LeavePageGuard implements CanDeactivate<isDeactivatable>{
  canDeactivate(
    component: isDeactivatable
  ): Observable<boolean> | Promise<boolean> | boolean {
    return component.canPageLeave();
  }
}

要前进到
PageB
我使用的是
布尔值
绕过导航
。在继续之前,我将此值设置为TRUE,方法
canPageLeave
将返回
TRUE

除以下情况外,前向导航在一种情况下不起作用

on PageA change some data and click on back button -> Confirmation pop up will open -> Select No -> Confirmation pop up will close and the same page remains open. Select button to move forward to PageB.
这会将导航移动到
pageB
,但也会使页面成为根页面并删除所有路由历史记录。在此流程之后,我无法从
PageB
返回

编辑:添加
isDeactivatable

export interface isDeactivatable {
    canPageLeave: () => Observable<boolean> | Promise<boolean> | boolean;
}
导出接口是可指定的{
canPageLeave:()=>可观察的|承诺|布尔值;
}
一个类可以实现为一个守卫的接口,决定是否可以停用路由。如果所有防护返回true,导航将继续。如果任何防护返回false,则取消导航如果任何防护返回UrlTree,则当前导航将被取消,新的导航将开始指向防护返回的UrlTree

在这种类型的守卫中,没有随机行为,这完全是关于你的守卫返回了什么!如果你的一个守卫返回一个UrlTree,这个将覆盖旧的UrlTree!我想这是你的情况


isDeactivatable
是一个组件吗?请添加完整的代码!您想要设置防护的组件,

看起来您只是想在向后导航时执行
canDeactivate
防护,而不是在向前导航时执行

如果是这种情况,请查看

您可以避免使用
旁路导航
(这样您就不需要手动更新其值),并通过以下方式稍微更新您的防护:

import { Injectable } from "@angular/core";
import { ActivatedRouteSnapshot, CanDeactivate, RouterStateSnapshot } from "@angular/router";
import { Observable } from "rxjs";

export interface isDeactivatable {
  canPageLeave: (
    nextUrl?: string // <--- here!
  ) => Observable<boolean> | Promise<boolean> | boolean;
}

@Injectable()
export class CanLeavePageGuard implements CanDeactivate<isDeactivatable> {
  canDeactivate(
    component: isDeactivatable,
    currentRoute: ActivatedRouteSnapshot,
    currentState: RouterStateSnapshot,
    nextState: RouterStateSnapshot
  ): Observable<boolean> | Promise<boolean> | boolean {
    return component.canPageLeave(nextState.url); // <--- and here!
  }
}


还有另一种“替代”方法,包括从
NavController
获取导航方向

这种方法更像是一种变通方法,因为导航方向实际上是
导航控制器
中的私有属性,但如果需要,我们仍然可以访问它:

async canPageLeave() {
    if (this.status === "saved") {
      return true;
    }   

    // ----------------------
    // Alternative approach
    // ----------------------
    // The direction is a private property from the NavController
    // but we can still use it to see if the user is going back
    // to HomePage or going forward to SecondPage.
    // ----------------------

    const { direction } = (this.navCtrl as unknown) as {
      direction: "forward" | "back" | "root";
    };

    if (direction !== "back") {
      return true;
    }

    const alert = await this.alertCtrl.create({
      header: "Unsaved Chnages",
      message: "Do you want to leave?",
      buttons: [
        {
          text: "No",
          role: "cancel",
          handler: () => {}
        },
        {
          text: "Yes",
          role: "goBack",
          handler: () => {}
        }
      ]
    });

    await alert.present();

    const data = await alert.onDidDismiss();

    if (data.role == "goBack") {
      return true;
    } else {
      return false;
    }
  }

这种方法听起来可能更简单,因为您不需要手动检查下一个url,但请记住,爱奥尼亚团队将来可能会在没有任何通知的情况下删除它(因为它是私有财产)因此,最好只使用上面解释的
nextUrl

您能提供问题的stackblitz最小表示形式吗?我将此值设置为TRUE。但您将此值设置为false,这是一个拼写错误吗?Hi@Nadhir,很抱歉回复太晚。isDeactivatable是我在教程中检查过的一个声明接口。另外,我没有返回任何UrlTree,只有在用户选择“否”停留在页面上时,我才在页面a上返回一个假值。根据上面的解释,当在页面a上返回一个假值时,导航被取消。这很好,因为同一页面显示“打开”,但向前移动到另一个页面B使其成为根页面。是否有w我可以在PageA上返回UrlTree,以便导航堆栈保持不变吗?嗨@Sebafereras,首先感谢您付出了这么多努力。我尝试了您的解决方案,一行更改使其工作。这是使用导航控制器和导航前进方法。在我的导航中,我使用角度路由器,试图避免导航控制r、 所以我试着在代码中用'this.router.navigateByUrl(“/second”);'代替'this.navCtrl.navigateForward(“/second”)结果和我的一样。第三页将没有后退按钮。我不知道为什么会这样,但如果我不能使它与路由器一起工作,我必须使用NavController。不建议在Ionic应用程序中直接使用路由器,特别是因为
NavController
是在路由器之上构建的一个抽象,用于handle页面转换和其他一些事情(例如,将页面设置为root在Angular中并不意味着什么,但在Ionic中却意味着什么)。事实上,如果您查看一下,就会发现
NavController
实际上使用了
this.router.navigateByUrl(…)
在幕后。但是如果您确实需要直接使用路由器,您可以像这样手动设置方向:
this.navController.setDirection('forward');this.router.navigateByUrl('…');
(方向可以是
'forward'
'back'
'root'
)@TapasMukherjee抱歉,忘了在上面的评论中给你贴标签:Psaved my day!tks
async canPageLeave(nextUrl?: string) {
    if (this.status === "saved") {
      return true;
    }

    if (nextUrl && !nextUrl.includes("home")) {
      return true;
    }

    const alert = await this.alertCtrl.create({
      header: "Unsaved Chnages",
      message: "Do you want to leave?",
      buttons: [
        {
          text: "No",
          role: "cancel",
          handler: () => {}
        },
        {
          text: "Yes",
          role: "goBack",
          handler: () => {}
        }
      ]
    });

    await alert.present();

    const data = await alert.onDidDismiss();

    if (data.role == "goBack") {
      return true;
    } else {
      return false;
    }
  }
async canPageLeave() {
    if (this.status === "saved") {
      return true;
    }   

    // ----------------------
    // Alternative approach
    // ----------------------
    // The direction is a private property from the NavController
    // but we can still use it to see if the user is going back
    // to HomePage or going forward to SecondPage.
    // ----------------------

    const { direction } = (this.navCtrl as unknown) as {
      direction: "forward" | "back" | "root";
    };

    if (direction !== "back") {
      return true;
    }

    const alert = await this.alertCtrl.create({
      header: "Unsaved Chnages",
      message: "Do you want to leave?",
      buttons: [
        {
          text: "No",
          role: "cancel",
          handler: () => {}
        },
        {
          text: "Yes",
          role: "goBack",
          handler: () => {}
        }
      ]
    });

    await alert.present();

    const data = await alert.onDidDismiss();

    if (data.role == "goBack") {
      return true;
    } else {
      return false;
    }
  }