I'm wondering what is a best way to load a form after getting the response from server. I wrote some code where it is getting data from server and in my component I am subscribing to the response, but My UI is loading before even I get the response.
I want to use this component for both adding and editing.
Component:
@Component({
selector: 'gate',
templateUrl: '/public/app/views/gate.html',
directives: [GateFormComponent, StrategyComponent],
providers : [MyService]
})
export class MyComponent {
private id:any;
constructor(private _routeParams:RouteParams, @Inject(MyModel) private myModel,
private myService : MyService) {
}
ngOnInit() {
this.id = this._routeParams.get("id");
if (this.id) {
this.gateDataModel.unique_display_id = parseInt(this.id);
this.myService.loadData(this.id)
.subscribe(response => console.log(response));
}
}
In my component, I am loading 2 components one of which has a form into which I have to load data once I get the response. And all this should only happen if I have an id available.
Service:
@Injectable()
export class MyService extends HTTPServices {
constructor(http:Http) {
super(http);
}
loadData(id:number) {
return this.query(url)
.map(res => res.json())
.catch(this.handleError)
}
private handleError(error:Response) {
console.log("Error : ", error);
return Observable.throw(error.text());
}
HTTPServices
export class HTTPServices {
private headers:Headers;
private http:Http;
defaultOptionsArgs:RequestOptionsArgs;
constructor(http:Http) {
this.http = http;
this.headers = new Headers();
this.headers.append('Content-Type', 'application/json');
this.defaultOptionsArgs = {
'headers': this.headers
};
}
create(servicePath:string, model:any, options?:RequestOptionsArgs) {
var url = this.getUrl(servicePath);
var options = options ? options : this.defaultOptionsArgs;
return this.http.post(url, JSON.stringify(model), options);
}
query(servicePath:string, options?:RequestOptionsArgs) {
var options = options ? options : this.defaultOptionsArgs;
return this.http.get(servicePath, options);
}
}
----Edited-----
Finally, I was able to add @CanActivate
and it is working.
@Component({
selector: 'gate',
templateUrl: '/public/app/views/gate.html',
directives: [ROUTER_DIRECTIVES, GateFormComponent, StrategyComponent]
})
@CanActivate(
(next: ComponentInstruction, prev: ComponentInstruction) => {
return new Promise((resolve) => {
let id = next.params["id"];
let injector = ReflectiveInjector.resolveAndCreate([HTTP_PROVIDERS]);
let http = injector.get(Http);
if(id){
http.get(URL)
.subscribe((response) => {
console.log(response)
next.routeData.data["response"] = response;
// continue
resolve(true);
}, (error) => {
resolve(false);
});
} else {
resolve(true);
}
});
}
)
export class MyComponent{
private id:any;
constructor(private _routeParams:RouteParams, @Inject(MyModel) private myModel, routeData: RouteData) {
console.log(routeData.get("response"));
}
}
The component is loading up and then I am getting the response
Thanks
If you leverage Angular2 routing (and it seems to be the case), you could use leverage the
OnActivate
interface and its routerOnActivate:You could return a promise that will be resolved when your data will be there. Here is a sample:
I had a similar question, but since the solution can be used for your usecase too, i would recommend to have a look at the accepted answer: How to manipulate a component on specific routes in Angular2
The basic idea is to extend the
router-outlet
directive and override theactivate()
function which will be called before the next route is activated and waits for a promise to resolve.For example you could do something like this:
I think you could easily change this for your purposes. You could utilize your
@RouteConfig
for example to hold some information on what should happen or be checked on a route change.Another approach would be to use the
@CanActivate
decorator like mentioned here already, but its a bit harder to accomplish. It just feels a bit hacky at this point. I could add this later if you're interested.I have been able to implement this using the resolve functions of the router (https://angular.io/docs/ts/latest/guide/router.html#!#resolve-guard). This enables the http calls to be made and the route only completes when the http call observable returns.
There are good examples here: https://angular.io/resources/live-examples/router/ts/plnkr.html
In you component you can just use
where
data
is a property that is set to some value when the response from the server arrived.