web-dev-qa-db-fra.com

Comment rediriger vers une URL externe depuis une route angular2 sans utiliser de composant?

J'aimerais créer une redirection externe, mais pour rendre tous les itinéraires cohérents, je pense qu'il serait agréable de tout faire (y compris les redirections externes) dans la configuration des états de routeur.

alors:

const appRoutes: Routes = [
  {path: '', component: HomeComponent},
  {path: 'first', component: FirstComponent},
  {path: 'second', component: SecondComponent},
  {path: 'external-link', /*would like to have redirect here*/}      
];

UPD: et Je ne veux pas utiliser de composant vide dans ce cas comme @ koningdavid suggéré. Cette solution me semble vraiment bizarre. Ce devrait être quelque chose de vraiment facile à implémenter dans de tels cas, sans composants virtuels.

47
Yaroslav Polubedov

Vous pouvez réaliser ce que vous voulez avec une astuce en utilisant l'option de résolution d'un itinéraire. La résolution est une valeur de donnée qu'Angular2 obtiendra pour que la route soit initialisée. Plus de détails vous pouvez trouver ici dans la documentation officielle.

J'ai essayé cette approche et ça marche. Exemple:

Ajoutez ceci à la section fournisseur (plus importez les classes requises depuis Routing)

@NgModule({
    providers: [
        {
            provide: 'externalUrlRedirectResolver',
            useValue: (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) =>
            {
                window.location.href = (route.data as any).externalUrl;
            }
        }
    ]
})

Ensuite, vous pouvez définir votre itinéraire comme ceci:

{
        path: 'test',
        component: AnyRandomComponent,
        resolve: {
            url: 'externalUrlRedirectResolver'
        },
        data: {
            externalUrl: 'http://www.google.com'
        }
    }

Cela redirigera vers l'URL externe. C'est un peu un moyen de bidouille vraiment. J'ai essayé d'obtenir le résultat sans utiliser le composant, mais vous devez utiliser soit redirectTo ou component ou children ou loadChildren. redirectTo ne déclenchera pas la résolution et je ne suis pas sûr des enfants, bien que vous puissiez expérimenter.

Vous pouvez l'implémenter dans une classe Nice plutôt que dans le fournisseur. Plus d'informations dans la documentation (voir la référence ci-dessus).

P.S. Je préférerais vraiment utiliser moi-même un composant de redirection, je pense. Utilisez simplement l’astuce avec les données et obtenez l’état du routeur avec externalUrl pour l’obtenir en paramètre.

59

Vous pouvez créer un RedirectGuard:

import {Injectable} from '@angular/core';
import {CanActivate, ActivatedRouteSnapshot, Router, RouterStateSnapshot} from '@angular/router';

@Injectable()
export class RedirectGuard implements CanActivate {

  constructor(private router: Router) {}

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {

      window.location.href = route.data['externalUrl'];
      return true;

  }
}

Importez-le dans app.module:

providers: [RedirectGuard],

Et définissez votre itinéraire:

{
     path: 'youtube',
     canActivate: [RedirectGuard],
     component: RedirectGuard,
     data: {
       externalUrl: 'https://www.youtube.com/'
     }
 }
27
Vitalii Shevchuk

Pour autant que je sache, le routeur NG2 ne prend pas en charge la redirection externe. Vous pouvez créer un composant de redirection en guise d'une solution de contournement.

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'redirect',
  template: 'redirecting...'
})
export class RedirectComponent implements OnInit {
  constructor() { }

  ngOnInit() {
    window.location.href = 'http://www.redirecturl.com'
  }
}

Et utilisez-le dans votre routage

{ path: 'login', component: RedirectComponent, pathmath: 'full'},
16
koningdavid

Hmm ...

Je pense que vous pouvez simplement demander l’URL au lieu d’appeler ng2 Router ...


Par exemple...

<a href="http://example.com">External</a>

au lieu de

<a routerLink="/someRoute" routerLinkActive="active">External</a>

OU

window.location.href = 'http://www.example.com'

au lieu de

this.router.navigate( [ '/someRoute', 'someParam' ] );

Droite...?

9
shramee

Le routeur ne peut pas rediriger en externe. Une ressource externe ne peut pas être un état de l'application.

Si c'est uniquement à des fins de clarté, en gardant toutes les routes visibles au même endroit, vous pouvez définir un autre tableau de constantes avec tous les chemins externes dans le même fichier que les routes.

4
Fiddles

Je suppose que vous ne voulez pas créer un composant pour chaque URL, c'est pourquoi vous cherchez à le faire sans composant ...

Donc, vous pouvez essayer de créer une fonction qui génère l'objet composant pour vous ...

Par exemple...

function generateLinkingComponent( url ) {
  // Generate your component using koningdavid's code
  // replace 'http://www.redirecturl.com' with url param
  // and return it...
}

Et ajoutez-le comme ceci dans la configuration de votre routeur ...

const appRoutes: Routes = [
  {path: '', component: HomeComponent},
  {path: 'first', component: FirstComponent},
  {path: 'second', component: SecondComponent},
  {path: 'external-link', component: generateLinkingComponent( 'http://example.com' )},
  {path: 'client-login', component: generateLinkingComponent( 'http://client-login.example.com' )},
  {path: 'admin-login', component: generateLinkingComponent( 'http://admin.example.com' )},
];

Ce sera facile avec JS ... mais vous ne savez pas comment on peut retourner une classe dans une fonction dans TypeScript ...

J'espère que ça t'as aidé...

2
shramee

Enveloppant la réponse d'Ilya:

Ajoutez ce module.

import { Component, Injectable, NgModule } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve } from '@angular/router';

@Component({
  template: ''
})
class ExternalLinkComponent {
  constructor() {
  }
}

@Injectable()
class ExternalLinkResolver implements Resolve<any> {
  resolve(route: ActivatedRouteSnapshot): any {
    window.location.href = route.data.targetUri;
    return true;
  }
}

export class ExternalRoute {
  data: {
    targetUri: string;
  };
  path: string;
  pathMatch = 'full';
  resolve = { link: ExternalLinkResolver };
  component = ExternalLinkComponent;

  constructor(path: string, targetUri: string) {
    this.path = path;
    this.data = { targetUri: targetUri };
  }

}

@NgModule({
  providers: [ ExternalLinkResolver ],
  declarations: [ExternalLinkComponent]
})
export class ExternalRoutesModule { }

Puis importez ExternalRoutesModule et ajoutez des instances de ExternalRoute.

const childRoutes: Routes = [
  new ExternalRoute('', '/settings/account'),
  { path: 'staff-profiles', component:  StaffProfilesComponent},
  { path: 'staff-assignments', component:  StaffAssignmentsComponent}
];

const routes: Routes = [
  { path: '', component: BaseComponent, children: childRoutes }
];

@NgModule({
  imports: [ ExternalRoutesModule, RouterModule.forChild(routes) ],
  exports: [ RouterModule ]
})
export class SettingsRoutingModule { }

Notez que je monte les routes de sous-module via loadChildren dans cet exemple.

1
Sam