কৌণিক 2: উপাদানটি রেন্ডার করার আগে ডেটা লোড করবেন কীভাবে?


143

উপাদানটি রেন্ডার হওয়ার আগে আমি আমার এপিআই থেকে একটি ইভেন্ট লোড করার চেষ্টা করছি। বর্তমানে আমি আমার API পরিষেবাটি ব্যবহার করছি যা আমি উপাদানটির 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>

আমার 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();
        }     
    }     
}

ফাংশনটিতে API কল করার আগে ngOnInitডেটা আনার আগে উপাদানটি রেন্ডার হয়ে যায় । সুতরাং আমি কখনই আমার ভিউ টেমপ্লেটে ইভেন্ট আইডি দেখতে পাচ্ছি না। সুতরাং দেখে মনে হচ্ছে এটি একটি এএসআইএনসি সমস্যা। আমি সম্পত্তি নির্ধারিত হওয়ার পরে ev( EventRegisterউপাদান) বাঁধাই করে কিছু কাজ evকরার আশা করেছি। দুঃখজনকভাবে সম্পত্তিটি সেট হওয়ার divসাথে এটি চিহ্নিত চিহ্নটি দেখায় না *ngIf="ev"

প্রশ্ন: আমি কি ভাল পন্থা ব্যবহার করছি? যদি না; উপাদানটি রেন্ডার শুরু হওয়ার আগে ডেটা লোড করার সর্বোত্তম উপায় কী?

উল্লেখ্য:ngOnInit পদ্ধতির এই ব্যবহার করা হয় angular2 টিউটোরিয়াল

সম্পাদনা করুন:

দুটি সম্ভাব্য সমাধান। প্রথমটি ছিল খনন করা 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);
}

উত্তর:


127

হালনাগাদ

মূল

যখন console.log(this.ev)পরে মৃত্যুদন্ড কার্যকর করা হয় this.fetchEvent();, এর অর্থ fetchEvent()কলটি শেষ হয় না, এর অর্থ কেবল এটি নির্ধারিত। যখন console.log(this.ev)মৃত্যুদন্ড কার্যকর করা হয়, সার্ভারে কল এমনকি করা হয় না এবং অবশ্যই এখনও একটি মান ফেরত দেয় না।

fetchEvent()ফিরতে পরিবর্তন aPromise

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

সম্পূর্ণ হওয়ার ngOnInit()জন্য অপেক্ষা করতে পরিবর্তন করুনPromise

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

এটি আসলে আপনার ব্যবহারের ক্ষেত্রে আপনাকে বেশি কিছু কিনবে না।

আমার পরামর্শ: আপনার সম্পূর্ণ টেমপ্লেটটি একটিতে মুড়ে দিন <div *ngIf="isDataAvailable"> (template content) </div>

এবং ভিতরে ngOnInit()

isDataAvailable:boolean = false;

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

3
আসলে, আপনার প্রথম মন্তব্যটি সুন্দরভাবে কাজ করেছে। আমি কেবলমাত্র পুরো fetchEventফাংশনটি সরিয়েছি এবং কেবলমাত্র apiService.get.eventফাংশনটি এতে ngOnInitরেখেছি এবং এটি আমার উদ্দেশ্য হিসাবে কাজ করেছে। ধন্যবাদ! আমি আপনাকে উত্তর হিসাবে তাড়াতাড়ি আপনি উত্তর গ্রহণ করব।
টম আ্যালবার্স

কোনও কারণে, আমি কৌনিক 1.x এ এই পদ্ধতির ব্যবহার করেছি। আইএমএইচও, এটি যথাযথ সমাধানের পরিবর্তে হ্যাক হিসাবে নেওয়া উচিত। আমাদের কৌণিক 5 এ আরও ভাল করা উচিত
উইন্ডমায়াও

আপনি কি সম্পর্কে ঠিক পছন্দ না? আমি মনে করি উভয় পন্থা পুরোপুরি ঠিক আছে।
গন্টার জ্যাচবাউয়ার 13

54

একটি দুর্দান্ত সমাধান যা আমি পেয়েছি তা হ'ল ইউআই তে কিছু করা:

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

কেবলমাত্র যখন: আইডাটালয়েডটি সত্য হয় পৃষ্ঠাটি রেন্ডার করা হয়।


3
আমি মনে করি যে এই সমাধানটি কেবল কৌনিক 1 এর জন্য নয় কৌণিক> = 2 কারণ অ্যাংুলারের একমুখী তথ্য প্রবাহের নিয়মটি তৈরি হওয়ার পরে ভিউটিতে আপডেট হওয়া নিষেধ করে। উপাদানগুলির ভিউ রচনা করার পরে এই দুটি হুকই আগুনে।
zt1983811

1
ডিভ মোটেও রেন্ডার্ড হয় না। আমরা এটিকে রেন্ডারিং থেকে বিরত রাখতে চাই না, আমরা এটি বিলম্ব করতে চাই। এটি কাজ না করার কারণ হ'ল কৌণিক 2 তে দুটি উপায় বাঁধা নেই। @ ফিল আপনি কীভাবে এটি আপনার জন্য কাজ করেছে তা ব্যাখ্যা করতে পারবেন?
ishandutt2007

1
ঠিক আছে, আমি এটি ব্যবহার করছিলাম ChangeDetectionStrategy.Push, এটি পরিবর্তন করে ChangeDetectionStrategy.Defaultএটি দুটি উপায়ে টেমপ্লেটের সাথে আবদ্ধ করা হয়েছে।
ishandutt2007

কৌণিক 6. কাজ।
টিডিপি

কৌনিক 2x এ কি দুর্দান্ত হ্যাক কাজ করে।
নিশিল ভাভে

48

আপনি Angular2 +রেজোলভার ব্যবহার করে আপনার ডেটা প্রি-আনতে পারেন , আপনার উপাদান সম্পূর্ণরূপে লোড হওয়ার আগে সমাধানকারীরা আপনার ডেটা প্রক্রিয়া করে।

এমন অনেকগুলি ক্ষেত্রে রয়েছে যে আপনি যদি কিছু ঘটতে থাকে তবেই আপনি আপনার উপাদানটি লোড করতে চান, উদাহরণস্বরূপ ড্যাশবোর্ডে নেভিগেট করুন কেবলমাত্র যদি ব্যক্তি ইতিমধ্যে লগ ইন করে থাকে তবে এই ক্ষেত্রে সমাধানকারীরা খুব সহজ।

আপনার উপাদানটিকে ডেটা প্রেরণের জন্য আপনি যেভাবে রেজোলভারটি ব্যবহার করতে পারেন তার জন্য আমি আপনার জন্য তৈরি করা সহজ চিত্রটি দেখুন।

এখানে চিত্র বর্ণনা লিখুন

আপনার কোডে রেজোলভার প্রয়োগ করা খুব সহজ, রেজোলভারটি কীভাবে তৈরি করা যায় তা দেখতে আমি আপনার জন্য স্নিপেট তৈরি করেছি:

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: MyResolver}}
////

1
আমার মনে হয় আপনি অধীনে রুট কনফিগারেশন এন্ট্রি মিস Routesঅ্যারে (সাধারণত মধ্যে app.routing.ts ফাইল):{path: 'yourpath/:id', component: YourComponent, resolve: { myData: MyData}}
Voicu

1
@ ভাইকু, এটি সমস্ত অংশকে কভার করার কথা নয়, তবে আমি একমত হয়েছি, এটি উত্তরটি আরও বিস্তৃত করে তুলেছে, তাই আমি যুক্ত করেছি ... ধন্যবাদ
আলিরিজা

5
কেবলমাত্র শেষ অংশটি সংশোধন করার জন্য, রুটের রেজোলিউশন প্যারামিটারটি ডেটা টাইপ নয়, বরং নিজেই রেজলভারের দিকে নির্দেশ করতে হবেresolve: { myData: MyResolver }
ক্রিস হেইনেস

মাইডাটা কি এমন কোনও মডেল অবজেক্ট যা মাই সার্ভিসে সংজ্ঞায়িত করে?
ইসুরু মাদুসঙ্কা

1
এই সমাধানটি পৃষ্ঠা লোড হওয়ার আগে ডেটা আনার জন্য ভাল তবে লগড ব্যবহারকারীর বা ব্যবহারকারীর ভূমিকার জন্য নয়। তার জন্য আপনার গার্ডস ব্যবহার করা উচিত
অ্যাঞ্জেল কিউ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.