कैसे कोणीय में एक मार्ग परिवर्तन का पता लगाने के लिए?


428

मैं अपने मार्ग में परिवर्तन का पता लगाने के लिए देख रहा हूँ AppComponent

उसके बाद मैं वैश्विक उपयोगकर्ता टोकन की जांच करूंगा कि वह लॉग इन है या नहीं। फिर मैं उपयोगकर्ता को रीडायरेक्ट कर सकता हूं यदि वह लॉग इन नहीं है।

जवाबों:


534

कोणीय 2 में आप subscribe(Rx घटना) को एक राउटर उदाहरण के लिए कर सकते हैं। तो आप जैसे काम कर सकते हैं

class MyClass {
  constructor(private router: Router) {
    router.subscribe((val) => /*whatever*/)
  }
}

संपादित करें (rc.1 के बाद से)

class MyClass {
  constructor(private router: Router) {
    router.changes.subscribe((val) => /*whatever*/)
  }
}

2 संपादित करें (2.0.0 से)

इन्हें भी देखें: Router.events डॉक्टर

class MyClass {
  constructor(private router: Router) {
    router.events.subscribe((val) => {
        // see also 
        console.log(val instanceof NavigationEnd) 
    });
  }
}

2
मुझे event._root.children[0].value._routeConfig.dataआशा है कि मैं बेहतर तरीके से डेटा प्राप्त कर सकता हूं
अक्षय

6
@Akshay आप टोड आदर्श वाक्य से इस लेख को देखा है: [रूटर घटनाओं के साथ कोणीय 2 में गतिशील पृष्ठ शीर्षक] ( toddmotto.com/dynamic-page-titles-angular-2-router-events )
Bogac

10
3 बार आग क्यों लगती है?
टूलकिट

2
@ टूलकिट क्योंकि इसकी घटना में 3 राज्य हैं और url के सफल परिवर्तन में है। 3 राज्य हैं: 'नेवीगेशनस्टार्ट', 'नेविगेशनएंड' और 'रूटसर्किटाइज़्ड'
रिकार्डो गॉनज़ेल्स

10
आप RxJS filterऑपरेटर के साथ आसानी से घटनाओं को फ़िल्टर कर सकते हैं । router.events.pipe(filter(e => e instanceof NavigationEnd).subscribe((e) => { ... }
सिमोन_वेर

314

आरएक्सजेएस 6

router.events.pipe(filter(event => event instanceof NavigationStart))

Peilonrayz के लिए धन्यवाद (नीचे टिप्पणी देखें)

नया राउटर> = RC.3

import { Router, NavigationStart, NavigationEnd, NavigationError, NavigationCancel, RoutesRecognized } from '@angular/router';

constructor(router:Router) {
  router.events.forEach((event) => {
    if(event instanceof NavigationStart) {
    }
    // NavigationEnd
    // NavigationCancel
    // NavigationError
    // RoutesRecognized
  });
}

आप दिए गए ईवेंट को भी फ़िल्टर कर सकते हैं:

import 'rxjs/add/operator/filter';

constructor(router:Router) {
  router.events
    .filter(event => event instanceof NavigationStart)
    .subscribe((event:NavigationStart) => {
      // You only receive NavigationStart events
    });
}

पिछली और वर्तमान घटना को प्राप्त करने के लिए pairwiseऑपरेटर का उपयोग करना भी एक अच्छा विचार है। https://github.com/angular/angular/issues/11268#issuecomment-244601977

import 'rxjs/add/operator/pairwise';
import { Router } from '@angular/router;

export class AppComponent {
    constructor(private router: Router) {
        this.router.events.pairwise().subscribe((event) => {
            console.log(event);
        });
    };
}

1
@GunterZochbauer 'के बजाय' मैं 'Instof' का उपयोग करेगा। और 'घटना: घटना' कोष्ठक में होनी चाहिए। इसके लिए धन्यवाद, बहुत शक्तिशाली नई सुविधा! मुझे यह पसंद है
मैक्सिम

2
यह वर्तमान संस्करणों पर एक संकलन त्रुटि को फेंक देता हैArgument of type '(event: Event) => void' is not assignable to parameter of type
रुडी स्ट्राइडम

1
@RudiStrydom & Günter Zöchbauer - Argument of type '(event: Event) => void' is not assignable to parameter of typeत्रुटि इसलिए है क्योंकि आपके फ़िल्टर स्निपेट में आप नेविगेशनईवेंट के बजाय इवेंट के ऑब्जेक्ट की सदस्यता ले रहे हैं।
बोनीकी

1
दूसरा नमूना ईवेंट के बजाय नेविगेशनईवेंट होना चाहिए।
मिक

1
आयात के बारे में संकेत किसी को भी इस त्रुटि को हल करने की तलाश में था :)
मिक

91

के लिए कोणीय 7 किसी की तरह लिखना चाहिए:

this.router.events.subscribe((event: Event) => {})


एक विस्तृत उदाहरण इस प्रकार हो सकता है:

import { Component } from '@angular/core'; 
import { Router, Event, NavigationStart, NavigationEnd, NavigationError } from '@angular/router';

@Component({
    selector: 'app-root',
    template: `<router-outlet></router-outlet>`
})
export class AppComponent {

    constructor(private router: Router) {

        this.router.events.subscribe((event: Event) => {
            if (event instanceof NavigationStart) {
                // Show loading indicator
            }

            if (event instanceof NavigationEnd) {
                // Hide loading indicator
            }

            if (event instanceof NavigationError) {
                // Hide loading indicator

                // Present error to user
                console.log(event.error);
            }
        });

   }
}

2
यह भी खूब रही! बहुत व्यापक! पूरी तरह से कोणीय 7.
MaylorTaylor

1
यदि आप प्रीलोडिंग रणनीति का उपयोग करते हैं तो आमतौर पर नेविगेशन में बहुत कम समय लगता है। प्रयोज्यता के संदर्भ में, मैं केवल बैकएंड http अनुरोधों पर लोडिंग संकेतक का उपयोग करूंगा, अगर सभी पर।
फिल

5
में निर्माता , आप उपयोग नहीं करना चाहिए <इस>, अपने मामले ngOnInit के लिए है।
सर्जियो रीस

1
बिल्कुल सही, मैं यूआरएल के सटीक param.id कैसे प्राप्त कर सकता हूं?
शिबिनराग

2
समाधान घटक सीमित नहीं है, यह संसाधनों का उपभोग करते हुए, पूरे ऐप में फैलता है
Md। रफ़ी

54

कोणीय 7 , आप चाहते हैं subscribeकरने के लिएrouter

import { Router, NavigationEnd } from '@angular/router';

import { filter } from 'rxjs/operators';

constructor(
  private router: Router
) {
  router.events.pipe(
    filter(event => event instanceof NavigationEnd)  
  ).subscribe((event: NavigationEnd) => {
    console.log(event.url);
  });
}

2
यह पुनर्निर्देशित घटना पर कब्जा नहीं करता है
आनंद अजयकुमार

40

कोणीय 4.x और ऊपर:

यह नीचे दिए गए के रूप में ActivatedRoute वर्ग की url संपत्ति का उपयोग करके प्राप्त किया जा सकता है ,

this.activatedRoute.url.subscribe(url =>{
     console.log(url);
});

नोट: आपको प्रदाता को angular/routerपैकेज से आयात और इंजेक्ट करने की आवश्यकता है

import { ActivatedRoute } from '@angular/router`

तथा

constructor(private activatedRoute : ActivatedRoute){  }

18

राउटर 3.0.0-beta.2 होना चाहिए

this.router.events.subscribe(path => {
  console.log('path = ', path);
});

कि वर्तमान पथ के लिए काम करता है लेकिन पिछले के बारे में क्या?
tatsu

16

कोणीय 6 और RxJS6 में:

import { filter, debounceTime } from 'rxjs/operators';

 this.router.events.pipe(
      filter((event) => event instanceof NavigationEnd),
      debounceTime(40000)
    ).subscribe(
      x => {
      console.log('val',x);
      this.router.navigate(['/']); /*Redirect to Home*/
}
)

3
आपने राउटर के लिए आयात को याद कियाimport {Router, NavigationEnd} from "@angular/router"
दमिर ब्यलखनोव

15

यहाँ के उत्तर सही हैं router-deprecated। के नवीनतम संस्करण के लिए router:

this.router.changes.forEach(() => {
    // Do whatever in here
});

या

this.router.changes.subscribe(() => {
     // Do whatever in here
});

दोनों के बीच अंतर देखने के लिए, कृपया इस SO प्रश्न को देखें

संपादित करें

नवीनतम के लिए आपको करना चाहिए:

this.router.events.subscribe(event: Event => {
    // Handle route change
});

क्या यह पिछले और वर्तमान मार्ग का कोई डेटा प्रदान करता है?
एक

routerफिर से अद्यतन किया गया है (मैं अपने जवाब अभी तक अपडेट नहीं किया है), इसलिए मुझे यकीन है कि यह कैसे नवीनतम के लिए है नहीं कर रहा हूँ। के बारे में routerमैंने लिखा है, आप नहीं कर सकते। @akn
देहली

क्या आप इस उत्तर के लिए कुछ संदर्भ प्रदान कर सकते हैं? आप के साथ अन्य समाधानों में कौन सी लाइनें बदल रही हैं?
जेरार्ड सिम्पसन

12

कोणीय 8 में आपको पसंद करना चाहिए this.router.events.subscribe((event: Event) => {})

उदाहरण:

import { Component } from '@angular/core'; 
import { Router, Event } from '@angular/router';
import { NavigationStart, NavigationError, NavigationEnd } from '@angular/router';

@Component({
    selector: 'app-root',
    template: `<router-outlet></router-outlet>`
})
export class AppComponent {

    constructor(private router: Router) {
        //Router subscriber
        this.router.events.subscribe((event: Event) => {
            if (event instanceof NavigationStart) {
                //do something on start activity
            }

            if (event instanceof NavigationError) {
                // Handle error
                console.error(event.error);
            }

            if (event instanceof NavigationEnd) {
                //do something on end activity
            }
        });
   }
}

10

घटक में, आप इसे आज़माना चाहते हैं:

import {NavigationEnd, NavigationStart, Router} from '@angular/router';

constructor(private router: Router) {
router.events.subscribe(
        (event) => {
            if (event instanceof NavigationStart)
                // start loading pages
            if (event instanceof NavigationEnd) {
                // end of loading paegs
            }
        });
}

8

निम्नलिखित तरीके से मार्ग परिवर्तन की घटनाओं को कैप्चर करें ...

import { Component, OnInit, Output, ViewChild } from "@angular/core";
import { Router, NavigationStart, NavigationEnd, Event as NavigationEvent } from '@angular/router';

@Component({
    selector: "my-app",
    templateUrl: "app/app.component.html",
    styleUrls: ["app/app.component.css"]
})
export class AppComponent {

    constructor(private cacheComponentObj: CacheComponent,
        private router: Router) {

        /*  Route event types
            NavigationEnd
            NavigationCancel
            NavigationError
            RoutesRecognized
        */
        router.events.forEach((event: NavigationEvent) => {

            //Before Navigation
            if (event instanceof NavigationStart) {
                switch (event.url) {
                case "/app/home":
                {
                    //Do Work
                    break;
                }
                case "/app/About":
                {
                    //Do Work
                    break;
                }
                }
            }

            //After Navigation
            if (event instanceof NavigationEnd) {
                switch (event.url) {
                case "/app/home":
                {
                    //Do Work
                    break;
                }
                case "/app/About":
                {
                    //Do Work
                    break;
                }
                }
            }
        });
    }
}

बिल्कुल सही, मैं यूआरएल के सटीक param.id कैसे प्राप्त कर सकता हूं?
शिबिनराग

6

स्थान कार्य करता है ...

import {Component, OnInit} from '@angular/core';
import {Location} from '@angular/common';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})

export class AppComponent implements OnInit {

    constructor(private location: Location) {
        this.location.onUrlChange(x => this.urlChange(x));
    }

    ngOnInit(): void {}

    urlChange(x) {
        console.log(x);
    }
}

अच्छा उत्तर। यह मेरे मामले के लिए काम करता है। साभार
उमर तारिक

4

अधिकांश समाधान सही हैं, लेकिन मैं इस समस्या का सामना कर रहा हूं, यह कई बार 'नेविगेशन उत्सर्जन' घटना है। जब भी इस घटना को चालू किया जाता है तो मैं बदल जाता था। तो सुनिए एंगुलर 6 का पूरा समाधान।

import { Subscription } from 'rxjs/Subscription';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/filter';    

export class FooComponent implements OnInit, OnDestroy {
   private _routerSub = Subscription.EMPTY;
   constructor(private router: Router){}

   ngOnInit(){
     this._routerSub = this.router.events
      .filter(event => event instanceof NavigationEnd)
      .subscribe((value) => {
         //do something with the value
     });
  }

  ngOnDestroy(){
   this._routerSub.unsubscribe();
  }
} 

3

@ ल्यूडेन का उत्तर बहुत अच्छा है, लेकिन यदि आप instanceofनिम्नलिखित का उपयोग नहीं करना चाहते हैं

this.router.events.subscribe(event => {
  if(event.constructor.name === "NavigationStart") {
    // do something...
  }
});

इस तरह से आप एक स्ट्रिंग के रूप में वर्तमान ईवेंट नाम की जांच कर सकते हैं और यदि ईवेंट हुआ है तो आप वही कर सकते हैं जो आपने करने के लिए अपने फ़ंक्शन की योजना बनाई थी।


3
क्यों नहीं टाइपस्क्रिप्ट सुरक्षा का उपयोग करें?
पास्कल

@ पास्कल से नफरत क्यों? और Eventप्रकार एटम में एक त्रुटि पैदा कर रहा है, इसीलिए मैंने इसका उपयोग नहीं किया
खालिद अल-अंसारी

2
@ पास्कल नहीं यह एक कोणीय समस्या है क्योंकि राउटर इवेंट ब्राउज़र इवेंट के समान नहीं है और इसीलिए इवेंट प्रकार काम नहीं करेगा! उन्हें इस घटना के लिए एक नया इंटरफ़ेस बनाने की आवश्यकता है, मुझे कहना चाहिए कि शुरुआत से लेकिन अनुचित नीचे वोट ने मदद नहीं की :)
खालिद अल-अंसारी

5
चूंकि उत्पादन कोड में खनन किया जाता है, instanceOfइसलिए आपको इसका उपयोग करना चाहिए ताकि आपका उदाहरण उत्पादन कोड में भी काम करेगा। if(event instanceOf NavigationStart) {
मिलन जरीक

1
होना चाहिएif(event instanceof NavigationStart)
केतन

1

मैं कोणीय 5 अनुप्रयोग के साथ काम कर रहा हूं और मैं उसी मुद्दे का सामना कर रहा हूं। जब मैं कोणीय दस्तावेज़ीकरण से गुजरता हूं तो वे राउटर घटनाओं से निपटने के लिए सबसे अच्छा समाधान प्रदान करते हैं। दस्तावेज़ के बाद जांच करें।

जब नेविगेशन सफलतापूर्वक समाप्त हो जाता है तो एक घटना का प्रतिनिधित्व करता है

इसका उपयोग कैसे करें?

import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRouteSnapshot, NavigationEnd } from '@angular/router';
@Component({
    selector: 'app-navbar',
    templateUrl: './navbar.component.html',
    styleUrls: ['./navbar.component.css']
})
export class NavbarComponent implements OnInit {
    constructor(private router: Router) { }
    ngOnInit(): void {
        //calls this method when navigation ends
        this.router.events.subscribe(event => {
            if (event instanceof NavigationEnd) {
                //calls this stuff when navigation ends
                console.log("Event generated");
            }
        });
    }
}

इसका उपयोग कब करें?

मेरे मामले में मेरा आवेदन सभी उपयोगकर्ताओं के लिए आम डैशबोर्ड साझा करता है जैसे कि उपयोगकर्ता, एडमीन, लेकिन मुझे उपयोगकर्ता प्रकार के अनुसार कुछ नौबार विकल्प दिखाने और छिपाने की आवश्यकता है।

इसीलिए जब भी url में परिवर्तन होता है, मुझे सेवा पद्धति पर कॉल करने की आवश्यकता होती है, जो प्रतिक्रिया के अनुसार उपयोगकर्ता जानकारी में लॉग इन करता है, मैं आगे के संचालन के लिए जाऊंगा।


0

निम्नलिखित काम करता है और आप के लिए मुश्किल हो सकता है।

// in constructor of your app.ts with router and auth services injected
router.subscribe(path => {
    if (!authService.isAuthorised(path)) //whatever your auth service needs
        router.navigate(['/Login']);
    });

दुर्भाग्य से यह बाद में मुझे पसंद है की तुलना में अनुमार्गण प्रक्रिया में पुनर्निर्देश करता है। onActivate()मूल लक्ष्य घटक के रीडायरेक्ट से पहले कहा जाता है।

एक @CanActivateडेकोरेटर है जिसे आप लक्ष्य घटक पर उपयोग कर सकते हैं लेकिन यह ए) केंद्रीकृत नहीं है और बी) इंजेक्शन सेवाओं से लाभ नहीं उठाता है।

यह बहुत अच्छा होगा अगर कोई भी प्रतिबद्ध होने से पहले एक मार्ग को केंद्रीय रूप से अधिकृत करने का बेहतर तरीका सुझा सकता है। मुझे यकीन है कि एक बेहतर तरीका होना चाहिए।

यह मेरा वर्तमान कोड है (मार्ग परिवर्तन को सुनने के लिए मैं इसे कैसे बदलूंगा?):

import {Component, View, bootstrap, bind, provide} from 'angular2/angular2';
import {ROUTER_BINDINGS, RouterOutlet, RouteConfig, RouterLink, ROUTER_PROVIDERS, APP_BASE_HREF} from 'angular2/router';    
import {Location, LocationStrategy, HashLocationStrategy} from 'angular2/router';

import { Todo } from './components/todo/todo';
import { About } from './components/about/about';

@Component({
    selector: 'app'
})

@View({
    template: `
        <div class="container">
            <nav>
                <ul>
                    <li><a [router-link]="['/Home']">Todo</a></li>
                    <li><a [router-link]="['/About']">About</a></li>
                </ul>
            </nav>
            <router-outlet></router-outlet>
        </div>
    `,
    directives: [RouterOutlet, RouterLink]
})

@RouteConfig([
    { path: '/', redirectTo: '/home' },
    { path: '/home', component: Todo, as: 'Home' },
    { path: '/about', component: About, as: 'About' }
])

class AppComponent {    
    constructor(location: Location){
        location.go('/');
    }    
}    
bootstrap(AppComponent, [ROUTER_PROVIDERS, provide(APP_BASE_HREF, {useValue: '/'})]);

मैंने देखा है कि लोग अपना ओडिट कोड जोड़ने के लिए राऊटरऑउटलेट का विस्तार करते हैं जो एक तरीका है। इसके बारे में gitHub पर बात की जा रही है, लेकिन अभी तक कोई निष्कर्ष नहीं निकला है। यहाँ Auth0
डेनिस स्मोलेक

आपकी प्रतिक्रिया के लिए धन्यवाद। क्या आप कोणीय 2 के लिए ऑरल सर्विस सीखने के लिए कोई अच्छा वीडियो जानते हैं?
AngularM

0

मैं इसे आरसी 5 के बाद से ऐसा करता हूं

this.router.events
  .map( event => event instanceof NavigationStart )
  .subscribe( () => {
    // TODO
  } );

0

जैसे AppRoutModule पर बदलाव करें

@NgModule({
imports: [RouterModule.forRoot(routes, { scrollPositionRestoration: 'enabled' })],
  exports: [RouterModule]
})

0

कोणीय 8. जांचें कि क्या वर्तमान मार्ग आधार मार्ग है

  baseroute: boolean;
  constructor(
    private router: Router,
  ) {
    router.events.subscribe((val: any) => {
      if (val.url == "/") {
        this.baseroute = true;
      } else {
        this.baseroute = false;
      }
    });
  }

0

मैं कुछ इस तरह लिखूंगा:

ngOnInit() {
this.routed = this.router.events.map( event => event instanceof NavigationStart )
  .subscribe(() => {
  } );
}

ngOnDestroy() {
this.routed.unsubscribe();
}

-3

कोणीय 8. के ​​लिए सरल उत्तर

constructor(private route:ActivatedRoute) {
  console.log(route);
}

1
यह केवल तात्कालिकता पर अमल नहीं है, यह होगा: केवल एक बार !? यह कोई हल नहीं है।
Satria
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.