Buscar..


Enrutamiento básico

El enrutador permite la navegación de una vista a otra según las interacciones del usuario con la aplicación.

Los siguientes son los pasos para implementar el enrutamiento básico en Angular 2:

Precaución básica : Asegúrate de tener la etiqueta.

    <base href='/'> 

como el primer hijo debajo de su etiqueta de cabecera en su archivo index.html. Esta etiqueta dice que su carpeta de aplicaciones es la raíz de la aplicación. Angular 2 entonces sabría organizar sus enlaces.

El primer paso es verificar si está señalando las dependencias de enrutamiento correctas / más recientes en package.json -

"dependencies": {
  ......
  "@angular/router": "3.0.0-beta.1",
  ......
}

El segundo paso es definir la ruta según su definición de clase:

class Route {
  path : string
  pathMatch : 'full'|'prefix'
  component : Type|string
  .........
}

En un archivo de rutas ( route/routes.ts ), importe todos los componentes que necesita configurar para diferentes rutas de enrutamiento. La ruta vacía significa que la vista se carga de forma predeterminada. ":" en la ruta indica un parámetro dinámico pasado al componente cargado.

Las rutas se ponen a disposición de la aplicación a través de la inyección de dependencia. El método ProviderRouter se llama con RouterConfig como parámetro para que pueda ser inyectado a los componentes para llamar a tareas específicas de enrutamiento.

import { provideRouter, RouterConfig } from '@angular/router';
import { BarDetailComponent } from '../components/bar-detail.component';
import { DashboardComponent } from '../components/dashboard.component';
import { LoginComponent } from '../components/login.component';
import { SignupComponent } from '../components/signup.component';

export const appRoutes: RouterConfig = [
  { path: '', pathMatch: 'full', redirectTo: 'login' },
  { path: 'dashboard', component: DashboardComponent },
  { path: 'bars/:id', component: BarDetailComponent },
  { path: 'login', component: LoginComponent },
  { path: 'signup',   component: SignupComponent }
];

export const APP_ROUTER_PROVIDER = [provideRouter(appRoutes)];

El tercer paso es arrancar el proveedor de ruta.

En sus main.ts (Puede ser cualquier nombre. Básicamente, debe estar definido en el archivo principal en systemjs.config)

import { bootstrap } from '@angular/platform-browser-dynamic';
import { AppComponent } from './components/app.component';
import { APP_ROUTER_PROVIDER } from "./routes/routes";

bootstrap(AppComponent, [ APP_ROUTER_PROVIDER ]).catch(err => console.error(err));

El cuarto paso es cargar / mostrar los componentes del enrutador según la ruta a la que se accede. La directiva se utiliza para indicar a angular dónde cargar el componente. Para utilizar importar los ROUTER_DIRECTIVES.

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

@Component({
  selector: 'demo-app',
  template: `
    ....................................
    <div>
      <router-outlet></router-outlet>
    </div>
    ....................................
  `,
  // Add our router directives we will be using
  directives: [ROUTER_DIRECTIVES]
})

Quinto paso es enlazar las otras rutas. De forma predeterminada, RouterOutlet cargará el componente para el cual se especifica la ruta vacía en el RouterConfig. La directiva RouterLink se usa con la etiqueta de anclaje html para cargar los componentes adjuntos a las rutas. RouterLink genera el atributo href que se utiliza para generar enlaces. Por ejemplo:

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

@Component({
  selector: 'demo-app',
  template: `
    <a [routerLink]="['/login']">Login</a>
    <a [routerLink]="['/signup']">Signup</a>      
    <a [routerLink]="['/dashboard']">Dashboard</a>
    <div>
      <router-outlet></router-outlet>
    </div>
  `,
  // Add our router directives we will be using
  directives: [ROUTER_DIRECTIVES]
})
export class AppComponent { }

Ahora, estamos bien con el enrutamiento a la ruta estática. RouterLink también admite la ruta dinámica al pasar parámetros adicionales junto con la ruta.

importar {Componente} desde '@ angular / core'; importe {ROUTER_DIRECTIVES} desde '@ angular / router';

@Component({
  selector: 'demo-app',
  template: `
        <ul>
          <li *ngFor="let bar of bars | async">
            <a [routerLink]="['/bars', bar.id]">
              {{bar.name}}
            </a>
          </li>
        </ul>
    <div>
      <router-outlet></router-outlet>
    </div>
  `,
  // Add our router directives we will be using
  directives: [ROUTER_DIRECTIVES]
})
export class AppComponent { }

RouterLink toma una matriz donde el primer elemento es la ruta de enrutamiento y los elementos subsiguientes son para los parámetros de enrutamiento dinámico.

Rutas infantiles

A veces tiene sentido anidar vistas o rutas entre sí. Por ejemplo, en el panel de control desea varias vistas secundarias, similares a las pestañas pero implementadas a través del sistema de enrutamiento, para mostrar los proyectos, contactos y mensajes de los usuarios. Para soportar tales escenarios, el enrutador nos permite definir rutas secundarias.

Primero ajustamos nuestro RouterConfig desde arriba y agregamos las rutas secundarias:

import { ProjectsComponent } from '../components/projects.component';
import { MessagesComponent} from '../components/messages.component';

export const appRoutes: RouterConfig = [
  { path: '', pathMatch: 'full', redirectTo: 'login' },
  { path: 'dashboard', component: DashboardComponent,
    children: [
      { path: '', redirectTo: 'projects', pathMatch: 'full' },
      { path: 'projects', component: 'ProjectsComponent' },
      { path: 'messages', component: 'MessagesComponent' }
    ] },
  { path: 'bars/:id', component: BarDetailComponent },
  { path: 'login', component: LoginComponent },
  { path: 'signup',   component: SignupComponent }
];

Ahora que tenemos nuestras rutas secundarias definidas, tenemos que asegurarnos de que esas rutas secundarias se puedan mostrar dentro de nuestro DashboardComponent , ya que ahí es donde hemos agregado las secundarias. Anteriormente aprendimos que los componentes se muestran en una etiqueta <router-outlet></router-outlet> . Similar declaramos otro RouterOutlet en el DashboardComponent :

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

@Component({
  selector: 'dashboard',
  template: `
    <a [routerLink]="['projects']">Projects</a>
    <a [routerLink]="['messages']">Messages</a>   
    <div>
      <router-outlet></router-outlet>
    </div>
  `
})
export class DashboardComponent { }

Como puede ver, hemos agregado otro RouterOutlet en el que se mostrarán las rutas secundarias. Por lo general, la ruta con una ruta vacía se mostrará, sin embargo, configuramos una redirección a la ruta de los projects , porque queremos que se muestre inmediatamente cuando se carga la ruta del dashboard . Dicho esto, necesitamos una ruta vacía, de lo contrario obtendrá un error como este:

Cannot match any routes: 'dashboard'

Entonces, al agregar la ruta vacía , es decir, una ruta con una ruta vacía, hemos definido un punto de entrada para el enrutador.

ResolveData

Este ejemplo le mostrará cómo puede resolver los datos obtenidos de un servicio antes de representar la vista de su aplicación.

Utiliza angular / router 3.0.0-beta.2 al momento de escribir

users.service.ts

...
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import { User } from './user.ts';



@Injectable()
export class UsersService {

    constructor(public http:Http) {}

    /**
     * Returns all users
     * @returns {Observable<User[]>}
     */
    index():Observable<User[]> {

        return this.http.get('http://mywebsite.com/api/v1/users')
            .map((res:Response) => res.json());
    }

    /**
     * Returns a user by ID
     * @param id
     * @returns {Observable<User>}
     */
    get(id:number|string):Observable<User> {

        return this.http.get('http://mywebsite.com/api/v1/users/' + id)
            .map((res:Response) => res.json());
    }
}

usuarios.resolver.ts

...
import { UsersService } from './users.service.ts';
import { Observable } from 'rxjs/Rx';
import {
    Resolve,
    ActivatedRouteSnapshot,
    RouterStateSnapshot
} from "@angular/router";




@Injectable()
export class UsersResolver implements Resolve<User[] | User> {

    // Inject UsersService into the resolver
    constructor(private service:UsersService) {}

    resolve(route:ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable<User[] | User> {
        // If userId param exists in current URL, return a single user, else return all users
        // Uses brackets notation to access `id` to suppress editor warning, may use dot notation if you create an interface extending ActivatedRoute with an optional id? attribute
        if (route.params['id']) return this.service.get(route.params['id']);
        return this.service.index();
    }
}

users.component.ts

Este es un componente de la página con una lista de todos los usuarios. Funcionará de manera similar para el componente de la página de detalles del usuario, reemplazará data.users con data.user o cualquier tecla definida en app.routes.ts (ver más abajo)

...
import { ActivatedRoute} from "@angular/router";



@Component(...)
export class UsersComponent {

    users:User[];


    constructor(route: ActivatedRoute) {
        route.data.subscribe(data => {
            // data['Match key defined in RouterConfig, see below']
            this.users = data.users;
        });
    }

    /**
     * It is not required to unsubscribe from the resolver as Angular's HTTP
     * automatically completes the subscription when data is received from the server
     */
}

app.routes.ts

...
import { UsersResolver } from './resolvers/users.resolver';



export const routes:RouterConfig = <RouterConfig>[
    ...
    {
        path: 'user/:id',
        component: UserComponent,
        resolve: {
            // hence data.user in UserComponent
            user: UsersResolver
        }
    },
    {
        path: 'users',
        component: UsersComponent,
        resolve: {
            // hence data.users in UsersComponent, note the pluralisation
            users: UsersResolver
        }
    },
    ...
]
...

app.resolver.ts

Opcionalmente, agrupar varios resolutores juntos.

IMPORTANTE: los servicios que se utilizan en la resolución deben importarse primero o obtendrá un 'No hay proveedor para ... Error de resolución'. Recuerde que estos servicios estarán disponibles en todo el mundo y que ya no tendrá que declararlos en ningún providers de componentes. Asegúrese de darse de baja de cualquier suscripción para evitar la pérdida de memoria

...
import { UsersService } from './users.service';
import { UsersResolver } from './users.resolver';

export const ROUTE_RESOLVERS = [
    ...,
    UsersService,
    UsersResolver
]

main.browser.ts

Los resolvers tienen que ser inyectados durante el arranque.

...
import {bootstrap} from '@angular/platform-browser-dynamic';
import { ROUTE_RESOLVERS } from './app.resolver';

bootstrap(<Type>App, [
    ...
    ...ROUTE_RESOLVERS
])
.catch(err => console.error(err));

Enrutamiento con niños

Al contrario de la documentación original, encontré que esta es la forma de anidar correctamente las rutas de los niños dentro del archivo app.routing.ts o app.module.ts (según sus preferencias). Este enfoque funciona cuando se usa WebPack o SystemJS.

El siguiente ejemplo muestra las rutas de inicio, inicio / contador y inicio / contador / obtener datos. Las primeras y últimas rutas son ejemplos de redirecciones. Finalmente, al final del ejemplo es una forma adecuada de exportar la Ruta a importar en un archivo separado. Por ej. app.module.ts

Para explicar con más detalle, Angular requiere que tenga una ruta sin ruta en la matriz secundaria que incluye el componente principal, para representar la ruta principal. Es un poco confuso, pero si piensa en una URL en blanco para una ruta secundaria, esencialmente sería igual a la misma URL que la ruta principal.

import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";

import { HomeComponent } from "./components/home/home.component";
import { FetchDataComponent } from "./components/fetchdata/fetchdata.component";
import { CounterComponent } from "./components/counter/counter.component";

const appRoutes: Routes = [
    {
        path: "",
        redirectTo: "home",
        pathMatch: "full"
    },
    {
        path: "home",            
        children: [
            {
                path: "",
                component: HomeComponent
            },
            {
                path: "counter",                    
                children: [
                    {
                        path: "",
                        component: CounterComponent
                    },
                    {
                        path: "fetch-data",
                        component: FetchDataComponent                            
                    }
                ]
            }
        ]
    },
    {
        path: "**",
        redirectTo: "home"
    }
];

@NgModule({
    imports: [
        RouterModule.forRoot(appRoutes)
    ],
    exports: [
        RouterModule
    ]
})
export class AppRoutingModule { }

Gran ejemplo y descripción a través de Siraj



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