简体   繁体   English

navigateByUrl 无法路由应用程序

[英]navigateByUrl is failing to route the application

I have a button on a tab page to reset the app for a user by removing a storage entry:我在标签页上有一个按钮,用于通过删除存储条目为用户重置应用程序:

export class Tab1Page {

  constructor(private router: Router, private storage: Storage, private toastController: ToastController) { }

  async resetSettings() {
    await this.storage.remove('welcomeComplete');

    const toast = await this.toastController.create({
      message: 'Your settings have been reset.',
      duration: 2000
    });
    await toast.present();

    console.log('before');
    this.router.navigateByUrl('/');
    console.log('after');
  }
}

In the brower debugger, I can see that the entry is getting deleted from storage.在浏览器调试器中,我可以看到条目正在从存储中删除。 I am also presented with the toast.我也得到了祝酒词。

However, for some reason, the navigateByUrl method does not seem to be firing.但是,出于某种原因,navigateByUrl 方法似乎没有触发。 The above pages sits at the url '/tabs/tab1'.以上页面位于 url '/tabs/tab1'。 Both console.log() statements are executed and there isn't an error in the console.两个 console.log() 语句都已执行,并且控制台中没有错误。

I'm pretty new to front end development, so apologies if this is a basic newbie question.我是前端开发的新手,如果这是一个基本的新手问题,我深表歉意。


Update更新

my app-routing.module.ts我的 app-routing.module.ts

import { NgModule } from '@angular/core';
import { PreloadAllModules, RouterModule, Routes } from '@angular/router';
import { WelcomeGuard } from './welcome/welcome.guard';

const routes: Routes = [
  { 
    path: '', 
    loadChildren: './tabs/tabs.module#TabsPageModule',
    canActivate: [WelcomeGuard]
  },
  { 
    path: 'welcome', 
    loadChildren: './welcome/welcome.module#WelcomePageModule',
  }
];
@NgModule({
  imports: [
    RouterModule.forRoot(routes, { enableTracing: true, preloadingStrategy: PreloadAllModules })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule {}

my welcome.guard.ts我的 welcome.guard.ts

import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router, CanActivate } from '@angular/router';
import { Observable } from 'rxjs';
import { Storage } from '@ionic/storage';

@Injectable({
  providedIn: 'root'
})
export class WelcomeGuard implements CanActivate  {

  constructor(private router: Router, private storage: Storage) {}

  async canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Promise<boolean> {

    const welcomeComplete = await this.storage.get('welcomeComplete');

    if (!welcomeComplete) {
      this.router.navigateByUrl('/welcome');
    }
    return true;
  }
}

I have changed my resetSettings() to the following:我已将我的 resetSettings() 更改为以下内容:

  async resetSettings() {
    await this.storage.remove('welcomeComplete');

    const toast = await this.toastController.create({
      message: 'Your settings have been reset.',
      duration: 2000
    });

    toast.onDidDismiss().then(() => {
      this.router.navigateByUrl('');
    });

    await toast.present();
  }

Changing resetSettings() didn't fix the issue.更改 resetSettings() 没有解决问题。

It is problem with your guard, below change in welcome.guard.ts can help这是你的守卫有问题,下面的welcome.guard.ts更改可以帮助

 if (!welcomeComplete) {
   this.router.navigateByUrl('/welcome');
   return false;
 }
 return true;

Reason:原因:

in resetSetting function after you call调用后在 resetSetting 函数中

toast.onDidDismiss().then(() => {
  this.router.navigateByUrl('');
});

It tries to navigate to url : '' that matches first object in route array that is它尝试导航到与路由数组中的第一个对象匹配的 url : ''

...
{ 
path: '', 
loadChildren: './tabs/tabs.module#TabsPageModule',
canActivate: [WelcomeGuard]
}
....

then it executes guard function and then you are returning true in any case, it means page got approaval to navigate to '/' and as you are in /tabs/tab1 which is child path of current route setting, so it does nothing and stays in same page.然后它执行保护功能,然后你在任何情况下都返回true ,这意味着页面获得了导航到“/”的批准,就像你在 /tabs/tab1 这是当前路由设置的子路径一样,所以它什么都不做并停留在同一页面。

router.navigatByUrl returns a promise with a boolean, which indicates whether routing was successful. router.navigatByUrl返回一个带有布尔值的promise,表示路由是否成功。 I would recommend to log, whether your routing is successful like this:我建议记录,您的路由是否成功,如下所示:

this.router.navigateByUrl('/').then(success => console.log(`routing status: ${success}`));

I'm guessing that the result will be false, because of your guard.我猜结果会是假的,因为你的警卫。 So if I am right, disable your WelcomeGuard by removing it from your route or returning true.因此,如果我是对的,请通过从您的路线中删除它或返回 true 来禁用您的 WelcomeGuard。

I guess the problem happens because of routing inside of the guard again, but returning true two lines later.我想问题是由于再次在警卫内部路由而发生的,但在两行之后返回 true 。

Like the others, I would check the route you are trying to navigate to matches your router path configuration:像其他人一样,我会检查您尝试导航的路线以匹配您的路由器路径配置:

this.router.navigateByUrl('/');

const routes: Routes = [
    {
        path: '/', component: YourComponent, pathMatch: 'full', data: {
        ...
        }
    },

My default route is usually ' ', as opposed to ' / '.我的默认路由通常是 ' ',而不是 ' / '。

They cover using router.navigate / router.navigateByUrl pretty well here: How to use router.navigateByUrl and router.navigate in Angular他们在这里很好地涵盖了使用 router.navigate / router.navigateByUrl: How to use router.navigateByUrl and router.navigate in Angular

If you include the rest of your relevant code, we might be able to help more with your specific issue.如果您包含其余的相关代码,我们或许能够为您的具体问题提供更多帮助。

I hope this helps you 👍希望对你有帮助👍

Make sure your services methods return an observable.确保您的服务方法返回一个 observable。

storage.service.ts storage.service.ts

import { Observable } from 'rxjs';

remove() {

  const obs = Observable.create(observer => {
    observer.next('Hello');

    // Throw an error.
    if (error) {
      observer.error("my error");
    }

  });

  return obs;

}

toastController.service.ts toastController.service.ts

import { Observable } from 'rxjs';

create() {

  const obs = Observable.create(observer => {
    observer.next('Hello');

    // Throw an error.
    if (error) {
      observer.error("my error");
    }

  });

  return obs;

}

Then consume然后消费

import { zip } from 'rxjs';


export class Tab1Page {

  constructor(
    private router: Router, 
    private storage: Storage, 
    private toastController: ToastController
  ) { 
    // this.resetSettings();
  }

  resetSettings() {
    const a = this.storage.remove('welcomeComplete');
    const b = this.toastController.create({
      message: 'Your settings have been reset.',
      duration: 2000
    });

    zip(a, b).subscribe( res => {
       this.router.navigateByUrl('/');
       // or
       this.router.navigate(['/']);
    });

  }
}

Should you will try with navigate instead of navigateByUrl您是否应该尝试使用导航而不是navigateByUrl

this.router.navigate(['/']);

Or或者

this.router.navigate(['']);

Also you could你也可以

toast.onDidDismiss().then(()=> {
  this.router.navigate(['/']);
});

Depending your router.取决于你的路由器。

In my case, it was happening because there was a redirection preceding the path resolution.在我的例子中,它的发生是因为在路径解析之前有一个重定向。

When accessing / , I was redirecting the user to /login so the login page could be loaded.访问/时,我将用户重定向到/login以便可以加载登录页面。

However, the path-matching strategy I was using was 'prefix' which means the Angular router would choose the redirection instruction for any route prefixed with / , ie, all routes .但是,我使用的路径匹配策略是“prefix”,这意味着 Angular 路由器将为任何前缀为/的路由选择重定向指令,即所有路由

Changing the path-matching strategy to 'full' instructed the Angular route to redirect to /login only when the full path is / .将路径匹配策略更改为“完整”指示 Angular 路由仅在完整路径为/时重定向到/login So, the / gets redirected to /login and the /forgot-password do not get redirected to /login anymore.因此, /被重定向到/login ,而/forgot-password不再被重定向到/login

  { 
    path: '', 
    redirectTo: 'login', 
    pathMatch: 'prefix' // <---- this should be 'full'
  }, 
  {
    path: 'login',
    loadChildren: () => import('./login').then(m => m.LoginPageModule),
  },
  {
    path: 'forgot-password',
    loadChildren: () => import('./forgot-password').then(m => m.ForgotPasswordPageModule)
  },

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM