typescript कोणीय 2: घटक को प्रस्तुत करने से पहले डेटा कैसे लोड करें?




angular angular2-services (3)

घटक प्रस्तुत होने से पहले मैं अपने एपीआई से एक ईवेंट लोड करने की कोशिश कर रहा हूं। वर्तमान में मैं अपनी एपीआई सेवा का उपयोग कर रहा हूं जिसे मैं घटक के ngOnInit फ़ंक्शन से कॉल करता हूं।

मेरा 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
    }
}

मेरा 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>

मेरी एपीआई सेवा

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();
        }     
    }     
}

ngOnInit फ़ंक्शन में API कॉल से पहले घटक को डेटा प्राप्त करने से पहले घटक प्रदान किया जाता है। इसलिए मुझे अपने दृश्य टेम्पलेट में ईवेंट आईडी कभी नहीं मिलती है। तो ऐसा लगता है कि यह एक ASYNC समस्या है। मुझे उम्मीद है कि ev संपत्ति के सेट के बाद कुछ काम करने के लिए ev ( EventRegister घटक) के बाध्यकारी की उम्मीद है। अफसोस की बात यह है कि जब संपत्ति सेट हो जाती है तो यह *ngIf="ev" के साथ चिह्नित div को नहीं दिखाती है।

प्रश्न: क्या मैं एक अच्छा दृष्टिकोण उपयोग कर रहा हूं? अगर नहीं; घटक प्रस्तुत करने से पहले डेटा लोड करने का सबसे अच्छा तरीका क्या है?

नोट: ngOnInit दृष्टिकोण इस कोणीय 2 ट्यूटोरियल में उपयोग किया जाता है।

संपादित करें:

दो संभावित समाधान। सबसे पहले fetchEvent को fetchEvent और ngOnInit फ़ंक्शन में API सेवा का उपयोग करना था।

ngOnInit() {
    this._apiService.get.event(this.eventId).then(event => this.ev = event);
}

दूसरा समाधान दिए गए उत्तर की तरह।

fetchEvent(): Promise<EventModel> {
    return this._apiService.get.event(this.eventId);
}

ngOnInit() {
    this.fetchEvent().then(event => this.ev = event);
}

आप Angular2 + में Resolvers का उपयोग कर अपने डेटा को पूर्व-प्राप्त कर सकते हैं, आपके घटक को पूरी तरह से लोड होने से पहले Resolvers आपके डेटा को संसाधित कर सकते हैं।

ऐसे कई मामले हैं जिन्हें आप केवल कुछ घटक होने पर ही अपना घटक लोड करना चाहते हैं, उदाहरण के लिए, यदि पहले से लॉग इन किया गया व्यक्ति केवल डैशबोर्ड पर नेविगेट करता है, तो इस मामले में Resolvers बहुत आसान हैं।

अपने घटक को डेटा भेजने के लिए आप जिस संकल्प का उपयोग कर सकते हैं, उसके लिए मैंने आपके लिए बनाए गए सरल आरेख को देखें।

अपने कोड में रिजॉल्वर को लागू करना बहुत आसान है, मैंने आपके लिए स्निपेट बनाया है यह देखने के लिए कि रिजॉल्वर कैसे बनाया जा सकता है:

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;
      }
    });
  }
}

और मॉड्यूल में :

import { MyResolver } from './my-resolver.service';

@NgModule({
  imports: [
    RouterModule.forChild(myRoutes)
  ],
  exports: [
    RouterModule
  ],
  providers: [
    MyResolver
  ]
})
export class MyModule { }

और आप इसे अपने घटक में इस तरह एक्सेस कर सकते हैं:

/////
 ngOnInit() {
    this.route.data
      .subscribe((data: { mydata: myData }) => {
        this.id = data.mydata.id;
      });
  }
/////

और रूट में इस तरह कुछ (आमतौर पर app.routing.ts फ़ाइल में):

////
{path: 'yourpath/:id', component: YourComponent, resolve: { myData: MyData}}
////

अद्यतन करें

मूल

जब console.log(this.ev) को इस के बाद निष्पादित किया जाता है this.fetchEvent(); इसका मतलब यह नहीं है कि fetchEvent() कॉल किया जाता है, इसका मतलब केवल यह निर्धारित है। जब console.log(this.ev) निष्पादित किया जाता है, तो सर्वर को कॉल भी नहीं किया जाता है और निश्चित रूप से अभी तक कोई मान वापस नहीं आया है।

एक Promise वापस करने के लिए fetchEvent() बदलें

 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
    });
 }

Promise पूरा करने के लिए इंतजार करने के लिए ngOnInit() बदलें

ngOnInit() {
    this.fetchEvent().then(() =>
    console.log(this.ev)); // Now has value;
}

यह वास्तव में आपके उपयोग के मामले के लिए आपको ज्यादा नहीं खरीदेंगे।

मेरा सुझाव: अपने पूरे टेम्पलेट को <div *ngIf="isDataAvailable"> (template content) </div> में लपेटें <div *ngIf="isDataAvailable"> (template content) </div>

और ngOnInit()

isDataAvailable:boolean = false;

ngOnInit() {
    this.fetchEvent().then(() =>
    this.isDataAvailable = true); // Now has value;
}

एक अच्छा समाधान जो मैंने पाया है वह यूआई पर कुछ ऐसा करना है जैसे:

<div *ngIf="isDataLoaded">
 ...Your page...
</div

केवल तभी: isDataLoaded सत्य है पृष्ठ को प्रस्तुत किया जाता है।