কৌনিক 2 এ রুটের মধ্যে নেভিগেট করার সময় লোডিং স্ক্রিনটি দেখান


124

যখন আমি কৌনিক 2 তে কোনও রুট পরিবর্তন করি তখন আমি কীভাবে লোডিং স্ক্রিনটি দেখাব?



4
উপরের লিঙ্কযুক্ত প্রশ্নটি (অ্যান্ড্রুএল 64 এর মন্তব্য) অ্যাঙ্গুলারজেএস সম্পর্কিত, "কৌণিক" (2+) নয়।
গ্যারি ম্যাকগিল

উত্তর:


196

বর্তমান কৌণিক রাউটার নেভিগেশন ইভেন্টগুলি সরবরাহ করে। আপনি এগুলিতে সাবস্ক্রাইব করতে পারেন এবং সেই অনুযায়ী ইউআই পরিবর্তন করতে পারেন। যেমন অন্যান্য ঘটনা গণনা করতে মনে রাখুন NavigationCancelএবং NavigationErrorক্ষেত্রে আপনার স্পিনার থামাতে রাউটার ট্রানজিশন ব্যর্থ হয়।

app.componal.ts - আপনার মূল উপাদান

...
import {
  Router,
  // import as RouterEvent to avoid confusion with the DOM Event
  Event as RouterEvent,
  NavigationStart,
  NavigationEnd,
  NavigationCancel,
  NavigationError
} from '@angular/router'

@Component({})
export class AppComponent {

  // Sets initial value to true to show loading spinner on first load
  loading = true

  constructor(private router: Router) {
    this.router.events.subscribe((e : RouterEvent) => {
       this.navigationInterceptor(e);
     })
  }

  // Shows and hides the loading spinner during RouterEvent changes
  navigationInterceptor(event: RouterEvent): void {
    if (event instanceof NavigationStart) {
      this.loading = true
    }
    if (event instanceof NavigationEnd) {
      this.loading = false
    }

    // Set loading state to false in both of the below events to hide the spinner in case a request fails
    if (event instanceof NavigationCancel) {
      this.loading = false
    }
    if (event instanceof NavigationError) {
      this.loading = false
    }
  }
}

app.componal.html - আপনার রুট ভিউ

<div class="loading-overlay" *ngIf="loading">
    <!-- show something fancy here, here with Angular 2 Material's loading bar or circle -->
    <md-progress-bar mode="indeterminate"></md-progress-bar>
</div>

পারফরম্যান্স উন্নত উত্তর : আপনি যদি আরও ভাল পদ্ধতিতে পারফরম্যান্সের বিষয়ে চিন্তা করেন তবে তা প্রয়োগ করা কিছুটা ক্লান্তিকর তবে পারফরম্যান্সের উন্নতি অতিরিক্ত কাজের জন্য মূল্যবান হবে। *ngIfশর্তসাপেক্ষে স্পিনারকে দেখাতে ব্যবহার করার পরিবর্তে , আমরা অ্যাংুলারকে লাভবান করতে পারি NgZoneএবং Rendererস্পিনারকে সরিয়ে / অফ করতে পারি যা স্পিনারের অবস্থা পরিবর্তন করার পরে অ্যাংুলারের পরিবর্তন সনাক্তকরণকে বাইপাস করবে। আমি এই পাওয়া ব্যবহার তুলনায় অ্যানিমেশন বাধামুক্ত করতে *ngIfঅথবা একটি asyncনল।

এটি কিছু টুইটের সাথে আমার আগের উত্তরের মতো:

app.componal.ts - আপনার মূল উপাদান

...
import {
  Router,
  // import as RouterEvent to avoid confusion with the DOM Event
  Event as RouterEvent,
  NavigationStart,
  NavigationEnd,
  NavigationCancel,
  NavigationError
} from '@angular/router'
import {NgZone, Renderer, ElementRef, ViewChild} from '@angular/core'


@Component({})
export class AppComponent {

  // Instead of holding a boolean value for whether the spinner
  // should show or not, we store a reference to the spinner element,
  // see template snippet below this script
  @ViewChild('spinnerElement')
  spinnerElement: ElementRef

  constructor(private router: Router,
              private ngZone: NgZone,
              private renderer: Renderer) {
    router.events.subscribe(this._navigationInterceptor)
  }

  // Shows and hides the loading spinner during RouterEvent changes
  private _navigationInterceptor(event: RouterEvent): void {
    if (event instanceof NavigationStart) {
      // We wanna run this function outside of Angular's zone to
      // bypass change detection
      this.ngZone.runOutsideAngular(() => {
        // For simplicity we are going to turn opacity on / off
        // you could add/remove a class for more advanced styling
        // and enter/leave animation of the spinner
        this.renderer.setElementStyle(
          this.spinnerElement.nativeElement,
          'opacity',
          '1'
        )
      })
    }
    if (event instanceof NavigationEnd) {
      this._hideSpinner()
    }
    // Set loading state to false in both of the below events to
    // hide the spinner in case a request fails
    if (event instanceof NavigationCancel) {
      this._hideSpinner()
    }
    if (event instanceof NavigationError) {
      this._hideSpinner()
    }
  }

  private _hideSpinner(): void {
    // We wanna run this function outside of Angular's zone to
    // bypass change detection,
    this.ngZone.runOutsideAngular(() => {
      // For simplicity we are going to turn opacity on / off
      // you could add/remove a class for more advanced styling
      // and enter/leave animation of the spinner
      this.renderer.setElementStyle(
        this.spinnerElement.nativeElement,
        'opacity',
        '0'
      )
    })
  }
}

app.componal.html - আপনার রুট ভিউ

<div class="loading-overlay" #spinnerElement style="opacity: 0;">
    <!-- md-spinner is short for <md-progress-circle mode="indeterminate"></md-progress-circle> -->
    <md-spinner></md-spinner>
</div>

1
দুর্দান্ত, আমি আপনার পদ্ধতির প্রশংসা করি এটা তোলে আমার সামনে আঘাত করেনি এবং আমি এই মর্মস্পর্শী ধারণা নিয়ে আমার লম্বা পদ্ধতি প্রতিস্থাপিত চেয়ে আমি রূপে ফিরিয়ে নিয়ে যেতে ছিল becuase আমি উপর নিয়ন্ত্রণ হারিয়ে router navigationএবং it triggering the spinnerতারপর না কি এটিকে থামাতে সক্ষম হচ্ছে। navigationInterceptorসমাধানের মতো মনে হচ্ছে তবে আমি নিশ্চিত নই যে অন্য কিছু ভাঙ্গার অপেক্ষায় আছে কিনা I'm যদি async requestsএটির সাথে মিশে যায় তবে এটি আবার সমস্যাটির পরিচয় দেবে, আমি মনে করি।
অঙ্কিত সিং

1
এটি কি কোন পর্যায়ে কাজ করেছে? এটি এখন কৌনিক 2.4.8 এর সাথে কাজ করছে না। পৃষ্ঠাটি সিঙ্ক্রোনাস। পুরো পৃষ্ঠা / প্যারেন্ট উপাদানটি রেন্ডার না হওয়া পর্যন্ত স্পিনার রেন্ডার হবে না এবং এটি নেভিগেশনএন্ডে। এটি স্পিনারের পয়েন্টকে পরাস্ত করে
techguy2000

1
অস্বচ্ছতা ব্যবহার করা দুর্দান্ত পছন্দ নয়। দৃশ্যত, এটি ভাল, তবে ক্রোমে, যদি লোডিং চিত্র / আইকনটি কোনও বোতাম বা পাঠ্যের উপরে থাকে, আপনি বোতামটি অ্যাক্সেস করতে পারবেন না। আমি এটি ব্যবহার displayকরতে noneবা এটি ব্যবহার করে পরিবর্তন করেছি inline
im1dermike

2
আমি এই পদ্ধতির পছন্দ, ভাল কাজ মানুষ! তবে আমার একটি সমস্যা আছে এবং আমি বুঝতে পারি না কেন, যদি আমি নেভিগেশনএন্ডে অ্যানিমেশন স্যুইচ না করি তবে আমি স্পিনার লোডিং দেখতে পাব, তবে আমি যদি মিথ্যাতে স্যুইচ করি তবে রুটগুলি এত দ্রুত পরিবর্তন হয় যাতে আমি কোনও অ্যানিমেশনও দেখতে পাচ্ছি না :( আমি চেষ্টা করেছি এমনকি নেটওয়ার্ক থ্রোটলিংয়ের সাথে সংযোগটি গতি কমিয়ে দেয় তবে এটি এখনও একই থাকে :( মোটেও লোড হচ্ছে না। আপনি দয়া করে আমাকে এই বিষয়ে কোনও পরামর্শ দিতে পারেন I আমি লোডিং উপাদানটিতে ক্লাস যোগ করে এবং মুছে ফেলার মাধ্যমে অ্যানিমেশনগুলি নিয়ন্ত্রণ করি Thanks ধন্যবাদ
d123546

1
আমি আপনার কোডটি অনুলিপি করার সময় আমি এই ত্রুটিটি পেয়েছি 'md-spinner' is not a known element:। আমি কৌণিকের কাছে বেশ নতুন। আপনি কি আমাকে বলতে পারেন ভুল হতে পারে?
মানু চদা

39

আপডেট: 3 এখন আমি নতুন রাউটারে আপগ্রেড করেছি, আপনি যদি CanDeactivateগার্ড ব্যবহার করেন তবে @ বোরিসেল্মেকের দৃষ্টিভঙ্গি কার্যকর হবে না । আমি আমার পুরানো পদ্ধতির অবজ্ঞান করছি, ie:এই উত্তর

UPDATE2 : নতুন-রাউটার বর্ণন প্রতিশ্রুতি এবং রাউটার ঘটনা উত্তর দ্বারা @borislemke স্পিনার বাস্তবায়ন প্রধান দৃষ্টিভঙ্গি আবরণ বলে মনে হয়, আমি এটা পরীক্ষিত havent't কিন্তু আমি এটা সুপারিশ।

আপডেট 1: আমি এই উত্তরটি লিখেছিলাম সেই যুগে Old-Router, যখন কেবলমাত্র একটি ইভেন্টের route-changedমাধ্যমে জানানো হত router.subscribe()। আমি নীচের পদ্ধতির ওভারলোডও অনুভব করেছি এবং এটি ব্যবহার করেই চেষ্টা করার চেষ্টা করেছি router.subscribe()এবং এটি সনাক্তকরণের কোনও উপায় না থাকায় এটি ব্যাকফায়ার হয়েছিল canceled navigation। সুতরাং আমাকে দীর্ঘ পদ্ধতির (ডাবল ওয়ার্ক) ফিরে যেতে হয়েছিল।


যদি আপনি Angular2 এ নিজের পথটি জানেন তবে আপনার যা প্রয়োজন তা এটি


Boot.ts

import {bootstrap} from '@angular/platform-browser-dynamic';
import {MyApp} from 'path/to/MyApp-Component';
import { SpinnerService} from 'path/to/spinner-service';

bootstrap(MyApp, [SpinnerService]);

রুট উপাদান- (মাই অ্যাপ)

import { Component } from '@angular/core';
import { SpinnerComponent} from 'path/to/spinner-component';
@Component({
  selector: 'my-app',
  directives: [SpinnerComponent],
  template: `
     <spinner-component></spinner-component>
     <router-outlet></router-outlet>
   `
})
export class MyApp { }

স্পিনার-অংশ (ততক্ষণে সক্রিয়ের মান পরিবর্তন করতে স্পিনার-পরিষেবাতে সাবস্ক্রাইব হবে)

import {Component} from '@angular/core';
import { SpinnerService} from 'path/to/spinner-service';
@Component({
  selector: 'spinner-component',
  'template': '<div *ngIf="active" class="spinner loading"></div>'
})
export class SpinnerComponent {
  public active: boolean;

  public constructor(spinner: SpinnerService) {
    spinner.status.subscribe((status: boolean) => {
      this.active = status;
    });
  }
}

স্পিনার-পরিষেবা (এই পরিষেবাটির বুটস্ট্র্যাপ)

পরিবর্তনের স্থিতি পরিবর্তন করতে স্পিনার-উপাদান দ্বারা সাবস্ক্রাইব হওয়ার জন্য একটি পর্যবেক্ষণযোগ্য সংজ্ঞা দিন এবং স্পিনারকে সক্রিয় / নিষ্ক্রিয় জানতে এবং সেট করতে ফাংশন করুন।

import {Injectable} from '@angular/core';
import {Subject} from 'rxjs/Subject';
import 'rxjs/add/operator/share';

@Injectable()
export class SpinnerService {
  public status: Subject<boolean> = new Subject();
  private _active: boolean = false;

  public get active(): boolean {
    return this._active;
  }

  public set active(v: boolean) {
    this._active = v;
    this.status.next(v);
  }

  public start(): void {
    this.active = true;
  }

  public stop(): void {
    this.active = false;
  }
}

অন্যান্য সমস্ত রুটের উপাদান

(নমুনা):

import { Component} from '@angular/core';
import { SpinnerService} from 'path/to/spinner-service';
@Component({
   template: `<div *ngIf="!spinner.active" id="container">Nothing is Loading Now</div>`
})
export class SampleComponent {

  constructor(public spinner: SpinnerService){} 

  ngOnInit(){
    this.spinner.stop(); // or do it on some other event eg: when xmlhttp request completes loading data for the component
  }

  ngOnDestroy(){
    this.spinner.start();
  }
}

এটাও দেখুন আমি অ্যানিমেশন ডিফল্টরূপে কৌণিক সমর্থন কতটা না করি।
অঙ্কিত সিং

আপনি আমাকে স্পিনার জন্য পরিষেবা লিখতে সাহায্য করতে পারেন? আমি নিজে অ্যানিমেশনগুলি করতে পারি এবং সিএসএসে নিজেও কী করতে পারি না তবে আপনি যদি আমাকে পরিষেবাটিতে সহায়তা করতে পারেন তবে ভালো লাগবে।
লুকাস


1
আমি spinner-serviceআপাতত কিছু কোড যুক্ত করেছি এটির কাজটি করার জন্য আপনার কেবল অন্য অংশে প্রয়োজন to এবং মনে রাখবেন এটি এর জন্যangular2-rc-1
অঙ্কিত সিং

1
প্রকৃতপক্ষে, এটি দুর্দান্ত এবং কার্যকর, পরীক্ষার উদ্দেশ্যে আমার টিপ আপনি এনজিওনিউটে সেটটাইমআউট (() => this.spinner.stop (), 5000) দিয়ে স্পিনার থামাতে বিলম্ব করতে পারেন
ঝোনাটাস ক্লিঙ্কাফ

10

কেন কেবল সাধারণ সিএসএস ব্যবহার করছেন না:

<router-outlet></router-outlet>
<div class="loading"></div>

এবং আপনার শৈলীতে:

div.loading{
    height: 100px;
    background-color: red;
    display: none;
}
router-outlet + div.loading{
    display: block;
}

বা এমনকি আমরা প্রথম উত্তরের জন্য এটি করতে পারি:

<router-outlet></router-outlet>
<spinner-component></spinner-component>

এবং তারপর সহজভাবে

spinner-component{
   display:none;
}
router-outlet + spinner-component{
    display: block;
}

এখানে কৌশলটি হ'ল, নতুন রুট এবং উপাদানগুলি সর্বদা রাউটার-আউটলেট পরে প্রদর্শিত হবে , তাই একটি সাধারণ সিএসএস নির্বাচকের সাহায্যে আমরা লোডিংটি প্রদর্শন করতে এবং আড়াল করতে পারি।


<router-outlet> আমাদের উপাদান থেকে প্যারেন্ট উপাদানগুলিতে স্থান দিতে দেয় না, তাই লোডিং ডিভিওটি লুকানো কিছুটা জটিল হবে।
প্রবীণ রানা

1
এছাড়াও আপনার অ্যাপ্লিকেশনটিতে প্রতি বার একবার তাত্ক্ষণিকভাবে স্পিনারকে দেখার জন্য যদি প্রচুর রুট পরিবর্তন হয় তবে এটি দুর্দান্ত বিরক্তিকর হতে পারে। আরএক্সজেএস ব্যবহার করা ভাল এবং একটি ডেবিউনড টাইমার সেট করা ভাল তাই এটি কেবল অল্প বিলম্বের পরে উপস্থিত হয়।
সাইমন_উইভার

2

প্রথম রুটের জন্য যদি আপনার বিশেষ যুক্তির প্রয়োজন হয় তবে আপনি নিম্নলিখিতটি করতে পারেন:

AppComponent

    loaded = false;

    constructor(private router: Router....) {
       router.events.pipe(filter(e => e instanceof NavigationEnd), take(1))
                    .subscribe((e) => {
                       this.loaded = true;
                       alert('loaded - this fires only once');
                   });

আমার পৃষ্ঠা ফুটারটি লুকানোর জন্য আমার এটির প্রয়োজন ছিল যা অন্যথায় পৃষ্ঠার শীর্ষে উপস্থিত ছিল appear এছাড়াও যদি আপনি কেবল প্রথম পৃষ্ঠার জন্য কোনও লোডার চান তবে আপনি এটি ব্যবহার করতে পারেন।


0

আপনি এই বিদ্যমান সমাধানটিও ব্যবহার করতে পারেন । ডেমো এখানে আছে । দেখে মনে হচ্ছে ইউটিউব লোডিং বার। আমি সবেমাত্র এটি পেয়েছি এবং এটি আমার নিজস্ব প্রকল্পে যুক্ত করেছি।


এটি সমাধানকারীদের সাহায্য করে? আমার সমস্যাটি হ'ল সমাধানকারীরা ডেটা ফিরিয়ে আনার সময় আমি স্পিনারকে কোথাও দেখাতে পারছি না কারণ আসল টার্গেট উপাদান এনজিওনিটকে এখনও বলা হয়নি !! আমার ধারণা ছিল স্পিনারকে এনজিওনাইটে দেখানো এবং রুট সাবস্ক্রিপশন থেকে সমাধানের তথ্য ফিরে আসার পরে এটি আড়াল করা
কুলদীপ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.