typescript - parametros - Angular2: ¿Cómo cargar datos antes de renderizar el componente?
pasar datos entre componentes angular 5 (3)
Puede buscar previamente sus datos utilizando Resolvers en Angular2 + , los Resolvers procesan sus datos antes de que su Componente se cargue por completo.
Hay muchos casos en los que desea cargar su componente solo si sucede algo, por ejemplo, vaya al Tablero solo si la persona ya inició sesión, en este caso, los Resolvers son muy útiles.
Mire el diagrama simple que creé para usted para ver una de las formas en que puede usar el solucionador para enviar los datos a su componente.
Aplicar Resolver a tu código es bastante simple, creé los fragmentos para que veas cómo se puede crear el Resolver:
import { Injectable } from ''@angular/core'';
import { Router, Resolve, RouterStateSnapshot, ActivatedRouteSnapshot } from ''@angular/router'';
import { MyData, MyService } from ''./my.service'';
@Injectable()
export class MyResolver implements Resolve<MyData> {
constructor(private ms: MyService, private router: Router) {}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<MyData> {
let id = route.params[''id''];
return this.ms.getId(id).then(data => {
if (data) {
return data;
} else {
this.router.navigate([''/login'']);
return;
}
});
}
}
y en el módulo :
import { MyResolver } from ''./my-resolver.service'';
@NgModule({
imports: [
RouterModule.forChild(myRoutes)
],
exports: [
RouterModule
],
providers: [
MyResolver
]
})
export class MyModule { }
y puedes acceder a él en tu Componente así:
/////
ngOnInit() {
this.route.data
.subscribe((data: { mydata: myData }) => {
this.id = data.mydata.id;
});
}
/////
Y en la ruta algo como esto (generalmente en el archivo app.routing.ts):
////
{path: ''yourpath/:id'', component: YourComponent, resolve: { myData: MyResolver}}
////
Estoy tratando de cargar un evento desde mi API antes de que el componente se procese. Actualmente estoy usando mi servicio API que llamo desde la función ngOnInit del componente.
Mi componente
EventRegister
:
import {Component, OnInit, ElementRef} from "angular2/core";
import {ApiService} from "../../services/api.service";
import {EventModel} from ''../../models/EventModel'';
import {Router, ROUTER_DIRECTIVES, ROUTER_PROVIDERS, RouteConfig, RouteParams, RouterLink} from ''angular2/router'';
import {FORM_PROVIDERS, FORM_DIRECTIVES, Control} from ''angular2/common'';
@Component({
selector: "register",
templateUrl: "/events/register"
// provider array is added in parent component
})
export class EventRegister implements OnInit {
eventId: string;
ev: EventModel;
constructor(private _apiService: ApiService,
params: RouteParams) {
this.eventId = params.get(''id'');
}
fetchEvent(): void {
this._apiService.get.event(this.eventId).then(event => {
this.ev = event;
console.log(event); // Has a value
console.log(this.ev); // Has a value
});
}
ngOnInit() {
this.fetchEvent();
console.log(this.ev); // Has NO value
}
}
Mi plantilla
EventRegister
<register>
Hi this sentence is always visible, even if `ev property` is not loaded yet
<div *ngIf="ev">
I should be visible as soon the `ev property` is loaded. Currently I am never shown.
<span>{{event.id }}</span>
</div>
</register>
Mi servicio API
import "rxjs/Rx"
import {Http} from "angular2/http";
import {Injectable} from "angular2/core";
import {EventModel} from ''../models/EventModel'';
@Injectable()
export class ApiService {
constructor(private http: Http) { }
get = {
event: (eventId: string): Promise<EventModel> => {
return this.http.get("api/events/" + eventId).map(response => {
return response.json(); // Has a value
}).toPromise();
}
}
}
El componente se procesa antes de que la llamada API en la función
ngOnInit
los datos.
Por lo tanto, nunca puedo ver la identificación del evento en mi plantilla de vista.
Entonces parece que este es un problema ASYNC.
Esperaba que el enlace del
ev
(componente
EventRegister
) hiciera algún trabajo después de que se estableciera la propiedad
ev
.
Lamentablemente, no muestra el
div
marcado con
*ngIf="ev"
cuando se establece la propiedad.
Pregunta: ¿Estoy usando un buen enfoque? Si no; ¿Cuál es la mejor manera de cargar datos antes de que el componente comience a renderizarse?
NOTA:
El enfoque
ngOnInit
se usa en este
tutorial angular2
.
EDITAR:
Dos posibles soluciones.
Primero fue
fetchEvent
del
fetchEvent
y simplemente usar el servicio API en la función
ngOnInit
.
ngOnInit() {
this._apiService.get.event(this.eventId).then(event => this.ev = event);
}
Segunda solución Como la respuesta dada.
fetchEvent(): Promise<EventModel> {
return this._apiService.get.event(this.eventId);
}
ngOnInit() {
this.fetchEvent().then(event => this.ev = event);
}
Una buena solución que he encontrado es hacer en la interfaz de usuario algo como:
<div *ngIf="isDataLoaded">
...Your page...
</div
Solo cuando: isDataLoaded es verdadero, se representa la página.
actualizar
-
Si usa el enrutador, puede usar ganchos de ciclo de vida o resolvers para retrasar la navegación hasta que lleguen los datos. https://angular.io/guide/router#milestone-5-route-guards
-
Para cargar datos antes de la representación inicial del componente raíz, se puede usar
APP_INITIALIZER
Cómo pasar parámetros renderizados desde el backend al método de arranque angular2
original
Cuando
console.log(this.ev)
se ejecuta después de
this.fetchEvent();
, esto no significa que se haya realizado la llamada
fetchEvent()
, solo significa que está programada.
Cuando se ejecuta
console.log(this.ev)
, la llamada al servidor ni siquiera se realiza y, por supuesto, aún no ha devuelto un valor.
Cambiar
fetchEvent()
para devolver una
Promise
fetchEvent(){
return this._apiService.get.event(this.eventId).then(event => {
this.ev = event;
console.log(event); // Has a value
console.log(this.ev); // Has a value
});
}
cambie
ngOnInit()
para esperar a que se complete la
Promise
ngOnInit() {
this.fetchEvent().then(() =>
console.log(this.ev)); // Now has value;
}
En realidad, esto no te comprará mucho para tu caso de uso.
Mi sugerencia: Envuelva toda su plantilla en un
<div *ngIf="isDataAvailable"> (template content) </div>
y en
ngOnInit()
isDataAvailable:boolean = false;
ngOnInit() {
this.fetchEvent().then(() =>
this.isDataAvailable = true); // Now has value;
}