En Angular 1.x, UI-Router fue mi herramienta principal para esto. Al devolver una promesa para los valores de "resolución", el enrutador simplemente esperaría a que se complete la promesa antes de presentar las directivas.
Alternativamente, en Angular 1.x, un objeto nulo no bloqueará una plantilla, por lo que si no me importa un renderizado temporalmente incompleto, puedo usar $digest para renderizar después de la promise.then() llena un objeto de modelo inicialmente vacío .
De los dos enfoques, si es posible, preferiría esperar para cargar la vista y cancelar la navegación de ruta si no se puede cargar el recurso. Esto me ahorra el trabajo de "des-navegar". EDITAR: Tenga en cuenta que esto significa específicamente que esta pregunta solicita un método de mejores prácticas o compatible con futuros de Angular 2 para hacer esto, ¡y pide evitar el "operador Elvis" si es posible! Por lo tanto, no seleccioné esa respuesta.
Sin embargo, ninguno de estos dos métodos funciona en Angular 2.0. Seguramente hay una solución estándar planeada o disponible para esto. ¿Alguien sabe qué es esto?
@Component() { template: '{{cats.captchans.funniest}}' } export class CatsComponent { public cats: CatsModel; ngOnInit () { this._http.get('/api/v1/cats').subscribe(response => cats = response.json()); } }La siguiente pregunta puede reflejar el mismo problema: la plantilla de renderizado de Angular 2 después de cargar la PROMESA con datos . Tenga en cuenta que la pregunta no tiene código ni respuesta aceptada.
Pruebe {{model?.person.name}} , esto debería esperar a que el modelo no esté undefined y luego renderizar.
Angular 2 se refiere a esto ?. sintaxis como el operador de Elvis . Es difícil encontrar una referencia a él en la documentación, así que aquí hay una copia en caso de que lo cambien/muevan:
El operador Elvis ( ?. ) y las rutas de propiedades nulas
El operador angular "Elvis" ( ?. ) es una forma fluida y conveniente de protegerse contra valores nulos e indefinidos en las rutas de propiedad. Aquí está, protegiendo contra una falla de renderizado de vista si currentHero es nulo.
The current hero's name is {{currentHero?.firstName}}Vamos a elaborar sobre el problema y esta solución en particular.
¿Qué sucede cuando la siguiente propiedad de título enlazada a datos es nula?
The title is {{ title }}La vista aún se representa, pero el valor mostrado está en blanco; solo vemos "El título es" sin nada después. Ese es un comportamiento razonable. Al menos la aplicación no falla.
Supongamos que la expresión de la plantilla involucra una ruta de propiedad como en el siguiente ejemplo donde mostramos el nombre de un héroe nulo.
The null hero's name is {{nullHero.firstName}}JavaScript arroja un error de referencia nula y también lo hace Angular:
TypeError: Cannot read property 'firstName' of null in [null]Peor aún, toda la vista desaparece.
Podríamos afirmar que este es un comportamiento razonable si creyéramos que la propiedad del héroe nunca debe ser nula. Si nunca debe ser nulo y, sin embargo, es nulo, hemos cometido un error de programación que debe detectarse y corregirse. Lanzar una excepción es lo correcto.
Por otro lado, los valores nulos en la ruta de la propiedad pueden estar bien de vez en cuando, especialmente cuando sabemos que los datos llegarán eventualmente.
Mientras esperamos los datos, la vista debe mostrarse sin quejas y la ruta de la propiedad nula debe mostrarse en blanco al igual que la propiedad del título.
Desafortunadamente, nuestra aplicación falla cuando el héroe actual es nulo.
Podríamos codificar ese problema con NgIf
<!--No hero, div not displayed, no error --><div *ngIf="nullHero">The null hero's name is {{nullHero.firstName}}</div>O podríamos intentar encadenar partes de la ruta de la propiedad con &&, sabiendo que la expresión se recupera cuando encuentra el primer valor nulo.
The null hero's name is {{nullHero && nullHero.firstName}}Estos enfoques tienen mérito, pero pueden ser engorrosos, especialmente si el camino de la propiedad es largo. Imagine protegerse contra un nulo en algún lugar de una ruta de propiedad larga como abcd
El operador angular "Elvis" ( ?. ) es una forma más fluida y conveniente de protegerse contra los valores nulos en las rutas de propiedad. La expresión se recupera cuando alcanza el primer valor nulo. La pantalla está en blanco, pero la aplicación continúa funcionando y no hay errores.
<!-- No hero, no problem! -->The null hero's name is {{nullHero?.firstName}}También funciona perfectamente con rutas de propiedades largas:
a?.b?.c?.d
El paquete @angular/router tiene la propiedad Resolve para rutas. De modo que puede resolver fácilmente los datos antes de representar una vista de ruta.
Ver: https://angular.io/docs/ts/latest/api/router/index/Resolve-interface.html
Ejemplo de documentos a partir de hoy, 28 de agosto de 2017:
class Backend { fetchTeam(id: string) { return 'someTeam'; } } @Injectable() class TeamResolver implements Resolve<Team> { constructor(private backend: Backend) {} resolve( route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any>|Promise<any>|any { return this.backend.fetchTeam(route.params.id); } } @NgModule({ imports: [ RouterModule.forRoot([ { path: 'team/:id', component: TeamCmp, resolve: { team: TeamResolver } } ]) ], providers: [TeamResolver] }) class AppModule {}Ahora su ruta no se activará hasta que los datos hayan sido resueltos y devueltos.
Acceso a datos resueltos en su componente
Para acceder a los datos resueltos desde dentro de su componente en tiempo de ejecución, existen dos métodos. Entonces, dependiendo de sus necesidades, puede usar:
route.snapshot.paramMap que devuelve una cadena, o elroute.paramMap que devuelve un Observable al que puede .subscribe() .Ejemplo:
// the no-observable method this.dataYouResolved= this.route.snapshot.paramMap.get('id'); // console.debug(this.licenseNumber); // or the observable method this.route.paramMap .subscribe((params: ParamMap) => { // console.log(params); this.dataYouResolved= params.get('id'); return params.get('dataYouResolved'); // return null }); console.debug(this.dataYouResolved);Espero que eso ayude.
EDITAR: El equipo angular ha lanzado el decorador @Resolve. Todavía necesita algunas aclaraciones sobre cómo funciona, pero hasta entonces tomaré la respuesta relacionada de otra persona aquí y proporcionaré enlaces a otras fuentes:
EDITAR: Esta respuesta funciona solo para Angular 2 BETA. El enrutador no se lanzó para Angular 2 RC a partir de esta edición. En cambio, cuando use Angular 2 RC, reemplace las referencias al router con router-deprecated para continuar usando el enrutador beta.
La forma futura de Angular2 de implementar esto será a través del decorador @Resolve. Hasta entonces, el facsímil más cercano es el decorador CanActivate Component, según Brandon Roberts. ver https://github.com/angular/angular/issues/6611
Aunque la versión beta 0 no admite proporcionar valores resueltos al Componente, está planificado y también se describe una solución alternativa aquí: Uso de Resolver en rutas Angular2
Puede encontrar un ejemplo beta 1 aquí: http://run.plnkr.co/BAqA98lphi4rQZAd/#/resolved . Utiliza una solución alternativa muy similar, pero utiliza con mayor precisión el objeto RouteData en lugar de RouteParams .
@CanActivate((to) => { return new Promise((resolve) => { to.routeData.data.user = { name: 'John' }Además, tenga en cuenta que también hay una solución alternativa de ejemplo para acceder a los valores "resueltos" de la ruta anidada/principal y otras características que espera si ha usado UI-Router 1.x.
Tenga en cuenta que también deberá inyectar manualmente cualquier servicio que necesite para lograr esto, ya que la jerarquía del Inyector angular no está disponible actualmente en el decorador CanActivate. La simple importación de un Inyector creará una nueva instancia del inyector, sin acceso a los proveedores desde bootstrap() , por lo que probablemente desee almacenar una copia de toda la aplicación del inyector de arranque. El segundo enlace Plunk de Brandon en esta página es un buen punto de partida: https://github.com/angular/angular/issues/4112