Buscar..


Observaciones

Hay algunos trucos más que podemos hacer con el enrutador (como restringir el acceso), pero se pueden cubrir en un tutorial separado.

Si necesita una nueva ruta, simplemente modifique app.routes.ts y siga los siguientes pasos:

  1. Importar el componente
  2. Añadir a la matriz de routes . Asegúrese de incluir una nueva path y component .

Bootstrapping

Ahora que las rutas están definidas, debemos informar a nuestra aplicación sobre las rutas. Para hacer esto, reinicie al proveedor que exportamos en el ejemplo anterior.

Encuentre su configuración de arranque (debería estar en main.ts , pero su millaje puede variar ).

//main.ts

import {bootstrap} from '@angular/platform-browser-dynamic';

//Import the App component (root component)
import { App } from './app/app';

//Also import the app routes
import { APP_ROUTES_PROVIDER } from './app/app.routes';

bootstrap(App, [
  APP_ROUTES_PROVIDER,
])
.catch(err => console.error(err));

Configurando enrutador de salida

Ahora que el enrutador está configurado y nuestra aplicación sabe cómo manejar las rutas, debemos mostrar los componentes reales que configuramos.

Para hacerlo, configure su plantilla / archivo HTML para su componente de nivel superior (aplicación) de la siguiente manera:

//app.ts

import {Component} from '@angular/core';
import {Router, ROUTER_DIRECTIVES} from '@angular/router';

@Component({
    selector: 'app',
    templateUrl: 'app.html',
    styleUrls: ['app.css'],
    directives: [
        ROUTER_DIRECTIVES,
    ]
})
export class App {
    constructor() {
    }
}

<!-- app.html -->

<!-- All of your 'views' will go here -->
<router-outlet></router-outlet>

El elemento <router-outlet></router-outlet> cambiará el contenido dado la ruta. Otro buen aspecto de este elemento es que no tiene que ser el único elemento en su HTML.

Por ejemplo: Digamos que quería una barra de herramientas en cada página que se mantiene constante entre las rutas, de forma similar al aspecto del Desbordamiento de pila. Puede anidar el <router-outlet> bajo los elementos para que solo cambien ciertas partes de la página.

Cambio de rutas (utilizando plantillas y directivas)

Ahora que las rutas están configuradas, necesitamos alguna forma de cambiar realmente las rutas.

Este ejemplo mostrará cómo cambiar las rutas usando la plantilla, pero es posible cambiar las rutas en TypeScript.

Aquí hay un ejemplo (sin enlace):

<a routerLink="/home">Home</a>

Si el usuario hace clic en ese enlace, se dirigirá a /home . El enrutador sabe cómo manejar /home , por lo que mostrará el componente de Home .

Aquí hay un ejemplo con enlace de datos:

<a *ngFor="let link of links" [routerLink]="link">{{link}}</a>

Lo que requeriría que existiera una matriz llamada links , así que agregue esto a app.ts :

public links[] = [
    'home',
    'login'
]

Esto recorrerá la matriz y agregará un elemento <a> con la directiva routerLink = el valor del elemento actual en la matriz, creando esto:

 <a routerLink="home">home</a>
 <a routerLink="login">login</a>

Esto es particularmente útil si tiene muchos enlaces, o tal vez los enlaces necesitan ser cambiados constantemente. Dejamos que Angular maneje el ajetreado trabajo de agregar enlaces con solo darle la información que requiere.

En este momento, los links[] son estáticos, pero es posible alimentarlos con datos de otra fuente.

Configuración de las rutas

NOTA: Este ejemplo se basa en la versión 3.0.0.-beta.2 de @ angular / router. Al momento de escribir esto, esta es la última versión del enrutador.

Para usar el enrutador, defina rutas en un nuevo archivo de TypeScript como el

//app.routes.ts

import {provideRouter} from '@angular/router';

import {Home} from './routes/home/home';
import {Profile} from './routes/profile/profile';

export const routes = [
    {path: '', redirectTo: 'home'},
    {path: 'home', component: Home},
    {path: 'login', component: Login},
];

export const APP_ROUTES_PROVIDER = provideRouter(routes);

En la primera línea, importamos provideRouter para que podamos informarle a nuestra aplicación cuáles son las rutas durante la fase de arranque.

Home y Profile son solo dos componentes como ejemplo. Deberá importar cada Component que necesite como ruta.

Luego, exporta la matriz de rutas.

path : la ruta al componente. NO NECESITA USAR '/ ........' Angular lo hará automáticamente

component : el componente a cargar cuando se accede a la ruta

redirectTo : opcional . Si necesita redirigir automáticamente a un usuario cuando accede a una ruta en particular, proporcione esto.

Finalmente, exportamos el enrutador configurado. provideRouter devolverá un proveedor al que podemos impulsar para que nuestra aplicación sepa cómo manejar cada ruta.

Control de acceso desde o hacia una ruta

El enrutador angular predeterminado permite navegar incondicionalmente hacia y desde cualquier ruta. Este no es siempre el comportamiento deseado.

En un escenario en el que se le puede permitir condicionalmente a un usuario navegar hacia o desde una ruta, se puede usar un Guardia de Ruta para restringir este comportamiento.

Si su escenario se ajusta a uno de los siguientes, considere usar un protector de ruta,

  • El usuario debe estar autenticado para navegar al componente de destino.
  • El usuario debe estar autorizado para navegar al componente de destino.
  • El componente requiere una solicitud asíncrona antes de la inicialización.
  • Componente requiere la entrada del usuario antes de navegar fuera de.

Cómo funcionan los guardias de ruta

Los guardias de ruta funcionan devolviendo un valor booleano para controlar el comportamiento de la navegación del enrutador. Si se devuelve true , el enrutador continuará con la navegación al componente de destino. Si se devuelve falso , el enrutador denegará la navegación al componente de destino.


Interfaces de guardia de ruta

El enrutador soporta múltiples interfaces de guarda:

  • CanActivate : se produce entre la navegación de ruta.
  • CanActivateChild : ocurre entre la navegación de la ruta a una ruta secundaria.
  • CanDeactivate : ocurre cuando se navega lejos de la ruta actual.
  • CanLoad : se produce entre la navegación de ruta a un módulo de función cargado de forma asíncrona.
  • Resolver : se utiliza para realizar la recuperación de datos antes de la activación de la ruta.

Estas interfaces se pueden implementar en su guardia para otorgar o eliminar el acceso a ciertos procesos de navegación.


Guardias de ruta sincrónica frente a asíncrona

Las protecciones de ruta permiten que las operaciones síncronas y asíncronas controlen condicionalmente la navegación.

Guardia de ruta sincrónica

Un protector de ruta síncrono devuelve un valor booleano, como al calcular un resultado inmediato, para controlar de forma condicional la navegación.

import { Injectable }     from '@angular/core';
import { CanActivate }    from '@angular/router';

@Injectable()
export class SynchronousGuard implements CanActivate {
  canActivate() {
    console.log('SynchronousGuard#canActivate called');
    return true;
  }
}

Guardia de ruta asíncrona

Para un comportamiento más complejo, un protector de ruta puede bloquear de forma asíncrona la navegación. Un protector de ruta asíncrono puede devolver una Observable o Promesa.

Esto es útil para situaciones como esperar la entrada del usuario para responder una pregunta, esperar para guardar con éxito los cambios en el servidor o esperar a recibir datos de un servidor remoto.

import { Injectable }     from '@angular/core';
import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Observable }     from 'rxjs/Rx';
import { MockAuthenticationService } from './authentication/authentication.service';

@Injectable()
export class AsynchronousGuard implements CanActivate {
    constructor(private router: Router, private auth: MockAuthenticationService) {}

    canActivate(route:ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable<boolean>|boolean {
        this.auth.subscribe((authenticated) => {
            if (authenticated) {
                return true;
            }
            this.router.navigateByUrl('/login');
            return false;
        });
    }
}

Añadir guardia a la configuración de la ruta

Archivo app.routes

Las rutas protegidas se han podido canActivate a Guard

import { provideRouter, Router, RouterConfig, CanActivate } from '@angular/router';

//components
import { LoginComponent } from './login/login.component';
import { DashboardComponent } from './dashboard/dashboard.component';

export const routes: RouterConfig = [
    { path: 'login', component: LoginComponent },
    { path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] }    
}

Exporte el APP_ROUTER_PROVIDERS para ser usado en la aplicación bootstrap

export const APP_ROUTER_PROVIDERS = [
    AuthGuard,
    provideRouter(routes)
];

Usa Guard en la aplicación bootstrap

Archivo main.ts (o boot.ts )

Considere los ejemplos anteriores:

  1. Crear la guardia (donde se crea la Guardia) y
  2. Agregar protección a la configuración de la ruta , (donde la Guardia está configurada para la ruta, luego se exporta APP_ROUTER_PROVIDERS ),
    Podemos acoplar el bootstrap a Guard de la siguiente manera
import { bootstrap } from '@angular/platform-browser-dynamic';
import { provide } from '@angular/core';

import { APP_ROUTER_PROVIDERS } from './app.routes';    
import { AppComponent } from './app.component';

bootstrap(AppComponent, [
    APP_ROUTER_PROVIDERS
])
.then(success => console.log(`Bootstrap success`))
.catch(error => console.log(error));

Uso de solucionadores y guardias

Estamos utilizando una protección de nivel superior en nuestra configuración de ruta para capturar al usuario actual en la carga de la primera página, y una resolución para almacenar el valor del currentUser , que es nuestro usuario autenticado desde el backend.

Una versión simplificada de nuestra implementación tiene el siguiente aspecto:

Aquí está nuestra ruta de nivel superior:

export const routes = [
{
  path: 'Dash',
  pathMatch : 'prefix',
  component: DashCmp,
  canActivate: [AuthGuard],
  resolve: {
      currentUser: CurrentUserResolver
  },
  children: [...[
    path: '',
    component: ProfileCmp,
    resolve: {
        currentUser: currentUser
    }
  ]]
  }
];

Aquí está nuestro servicio de AuthService

import { Injectable } from '@angular/core';
import { Http, Headers, RequestOptions } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import 'rxjs/add/operator/do';

@Injectable()
export class AuthService {
  constructor(http: Http) {
    this.http = http;

    let headers = new Headers({ 'Content-Type': 'application/json' });
    this.options = new RequestOptions({ headers: headers });
  }
  fetchCurrentUser() {
    return this.http.get('/api/users/me')
      .map(res => res.json())
      .do(val => this.currentUser = val);
 }
}

Aquí está nuestro AuthGuard :

import { Injectable } from '@angular/core';
import { CanActivate } from "@angular/router";
import { Observable } from 'rxjs/Rx';

import { AuthService } from '../services/AuthService';

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(auth: AuthService) {
    this.auth = auth;
  }
  canActivate(route, state) {
    return Observable
      .merge(this.auth.fetchCurrentUser(), Observable.of(true))
      .filter(x => x == true);
  }
}

Aquí está nuestro CurrentUserResolver :

import { Injectable } from '@angular/core';
import { Resolve } from "@angular/router";
import { Observable } from 'rxjs/Rx';

import { AuthService } from '../services/AuthService';

@Injectable()
export class CurrentUserResolver implements Resolve {
  constructor(auth: AuthService) {
    this.auth = auth;
  }
  resolve(route, state) {
    return this.auth.currentUser;
  }
}


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow