कोणीय 2 में मार्गों के बीच नेविगेट करते समय लोडिंग स्क्रीन दिखाएं


124

जब मैं कोणीय 2 में मार्ग बदलता हूं तो मैं लोडिंग स्क्रीन कैसे दिखा सकता हूं?



4
उपरोक्त जुड़ा हुआ प्रश्न (एंड्रयूएल 64 की टिप्पणी) एंगुलरजेएस के बारे में है, न कि "कोणीय" (2+) के बारे में।
गैरी मैकगिल

जवाबों:


196

वर्तमान कोणीय राउटर नेविगेशन इवेंट प्रदान करता है। आप इनकी सदस्यता ले सकते हैं और तदनुसार UI परिवर्तन कर सकते हैं। याद रखें अन्य घटनाओं में जैसे कि NavigationCancelऔर NavigationErrorअपने रनर को रोकने के मामले में राउटर संक्रमण विफल हो जाते हैं।

app.component.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.component.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.component.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.component.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
महान, मैं आपके दृष्टिकोण की सराहना करता हूं। यह मेरे से पहले मारा गया है और मैं इस अपील विचार के साथ मेरी लंबी विधि बदल दिया, की तुलना में मैं वापस लौटने के लिए किया था क्योंकि मैं पर नियंत्रण खो दिया router navigationऔर it triggering the spinnerऔर उसके बाद नहीं इसे रोकने के लिए सक्षम किया जा रहा। navigationInterceptorएक समाधान की तरह लगता है, लेकिन मुझे यकीन नहीं है कि कुछ और टूटने का इंतजार कर रहा है। अगर इसमें मिलावट async requestsफिर से समस्या का परिचय देगी, मुझे लगता है।
अंकित सिंह

1
शायद यह कुछ बिंदु पर काम किया? यह अब Angular 2.4.8 के साथ काम नहीं कर रहा है। पृष्ठ समकालिक है। पूरे पेज / पैरेंट कंपोनेंट को रेंडर करने तक, और नेविगेशनइंड पर, जब तक स्पिनर रेंडर नहीं हो जाता। उस स्पिनर की बात को हराया
Techguy2000

1
अपारदर्शिता का उपयोग करना एक बढ़िया विकल्प नहीं है। नेत्रहीन, यह ठीक है, लेकिन क्रोम में, यदि लोडिंग छवि / आइकन बटन या पाठ के शीर्ष पर है, तो आप बटन तक नहीं पहुंच सकते। मैंने इसे या displayतो उपयोग करने के लिए बदल दिया noneया inline
im1dermike

2
मुझे यह तरीका पसंद है, अच्छा काम करने वाला आदमी! लेकिन मेरे पास एक मुद्दा है और मुझे समझ में नहीं आता है, अगर मैं नेविगेशन पर एनीमेशन स्विच नहीं करता हूं, तो मैं स्पिनर लोडिंग देख सकता हूं, लेकिन अगर मैं गलत पर स्विच करता हूं, तो मार्ग इतनी तेजी से बदलते हैं कि मैं कोई भी एनिमेशन नहीं देख सकता :( मैंने कोशिश की है कनेक्शन को धीमा करने के लिए नेटवर्क थ्रोटलिंग के साथ, लेकिन इसका अभी भी समान है :( कोई लोडिंग नहीं है। क्या आप मुझे इस पर कोई सुझाव दे सकते हैं। मैं लोडिंग तत्व पर क्लास को जोड़कर और हटाकर एनिमेशन को नियंत्रित करता हूं। धन्यवाद
d123546

1
मुझे यह त्रुटि तब मिली जब मैंने आपका कोड कॉपी किया 'md-spinner' is not a known element:। मैं कोणीय के लिए काफी नया हूं। क्या आप मुझे बता सकते हैं कि क्या गलती हो सकती है?
मनु चड्ढा

40

अद्यतन: 3 अब जब मैंने नए राउटर में अपग्रेड किया है, अगर आप गार्ड का उपयोग करते हैं तो @borislemke का दृष्टिकोण काम नहीं करेगा CanDeactivate। मैं अपनी पुरानी विधि को नीचा दिखा रहा हूं, ie:यह जवाब

UPDATE2 : नए-राउटर में राउटर इवेंट आशाजनक दिखते हैं और @borislemke द्वारा उत्तर स्पिनर कार्यान्वयन के मुख्य पहलू को कवर करने के लिए लगता है, मैंने इसका परीक्षण नहीं किया है लेकिन मैं इसकी सलाह देता हूं।

UPDATE1: मैंने यह उत्तर उस युग में लिखा था 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]);

रूट घटक- (MyApp)

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

यह भी देखें । मैं डिफ़ॉल्ट रूप से कोणीय समर्थन कितना एनीमेशन नहीं करता।
अंकित सिंह

क्या आप मुझे स्पिनर के लिए सेवा लिखने में मदद कर सकते हैं? मैं स्वयं CSS में एनिमेशन और व्हाट्सएप कर सकता हूं, लेकिन यह अच्छा होगा यदि आप सेवा में मेरी मदद कर सकते हैं।
लुकास


1
मैंने spinner-serviceअभी कुछ कोड जोड़े हैं, आपको इसे काम करने के लिए अन्य भागों की आवश्यकता है। और यह याद रखें किangular2-rc-1
अंकित सिंह

1
वास्तव में, यह कमाल है और काम करता है, परीक्षण के उद्देश्यों के लिए मेरी टिप आप स्पिनर के स्टॉप को सेटटाइमआउट () => this.spinner.stop (), 5000) के साथ ngOnInit में बंद कर सकते हैं
झोनटास क्लिंकरफ

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

यहां चाल है, नए मार्गों और घटकों को हमेशा राउटर-आउटलेट के बाद दिखाई देगा , इसलिए एक साधारण सीएसएस चयनकर्ता के साथ हम लोडिंग दिखा सकते हैं और छिपा सकते हैं।


<राउटर-आउटलेट> हमें घटक से मूल घटक तक मान पारित करने की अनुमति नहीं देता है, इसलिए लोडिंग डिव को छिपाने के लिए यह थोड़ा जटिल होगा।
प्रवीण राणा

1
यह भी सुपर कष्टप्रद हो सकता है अगर आपके आवेदन में हर बार तुरन्त स्पिनर को देखने के लिए बहुत सारे मार्ग परिवर्तन हों। RxJs का उपयोग करना और एक विवादित टाइमर सेट करना बेहतर है, इसलिए यह केवल थोड़ी देरी के बाद दिखाई देता है।
सिमोन_विवर

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

मुझे अपने पृष्ठ पाद लेख को छिपाने के लिए इसकी आवश्यकता थी, जो अन्यथा पृष्ठ के शीर्ष पर दिखाई दे रहा था। इसके अलावा अगर आप केवल पहले पेज के लिए लोडर चाहते हैं तो आप इसका उपयोग कर सकते हैं।


0

आप इस मौजूदा समाधान का भी उपयोग कर सकते हैं । डेमो यहाँ है । यह यूट्यूब लोडिंग बार की तरह दिखता है। मैंने अभी इसे पाया और इसे अपने प्रोजेक्ट में जोड़ा।


क्या यह रिवाल्वर के साथ मदद करता है? मेरी समस्या यह है कि जब रिज़ॉल्वर्स डेटा वापस लाते हैं, तो मैं कहीं भी स्पिनर दिखाने में असमर्थ हूं क्योंकि वास्तविक लक्ष्य घटक एनगोनिनिट को अभी तक नहीं बुलाया गया है !! मेरा विचार स्पिनर को ngOnInit में दिखाना था और एक बार डेटा को रूट सब्सक्रिप्शन से वापस करने के बाद उसे छिपा देना था
kuldeep
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.