मैं एंगुलर रूट किए गए घटकों को डेटा कैसे पास करूं?


268

मेरे एक कोणीय 2 मार्गों के टेम्पलेट्स ( FirstComponent ) में मेरे पास एक बटन है

first.component.html

<div class="button" click="routeWithData()">Pass data and route</div>

मेरा लक्ष्य हासिल करना है:

बटन क्लिक -> डेटा को संरक्षित करते हुए और निर्देश के रूप में अन्य घटक का उपयोग किए बिना किसी अन्य घटक के लिए मार्ग।

यही मैंने कोशिश की ...

1ST APPROACH

उसी दृश्य में मैं उपयोगकर्ता सहभागिता के आधार पर समान डेटा एकत्र कर रहा हूं।

first.component.ts

export class FirstComponent {
     constructor(private _router: Router) { }

     property1: number;
     property2: string;
     property3: TypeXY; // this a class, not a primitive type

    // here some class methods set the properties above

    // DOM events
    routeWithData(){
         // here route
    }
}

आम तौर पर मैं द्वारा SecondComponent के लिए मार्ग होगा

 this._router.navigate(['SecondComponent']);

अंततः डेटा पास करके

 this._router.navigate(['SecondComponent', {p1: this.property1, p2: property2 }]);

जबकि मापदंडों के साथ लिंक की परिभाषा होगी

@RouteConfig([
      // ...
      { path: '/SecondComponent/:p1:p2', name: 'SecondComponent', component: SecondComponent} 
)]

इस दृष्टिकोण के साथ मुद्दा यह है कि मुझे लगता है कि मैं जटिल डेटा (जैसे प्रॉपर्टी 3 जैसी कोई वस्तु ) पास नहीं कर सकता ;

2 एन डी अप्रोच

FirstComponent में निर्देश के रूप में SecondComponent सहित एक विकल्प होगा ।

  <SecondComponent [p3]="property3"></SecondComponent>

हालाँकि मैं उस घटक को रूट करना चाहता हूं , लेकिन इसमें शामिल नहीं है!

3 आरडी अप्रोच

सबसे व्यवहार्य समाधान जो मैं यहां देख रहा हूं वह एक सेवा (जैसे FirstComponentService) का उपयोग करना होगा

  • स्टोर FirstComponent में डेटा routeWithData पर (_firstComponentService.storeData ()) ()
  • डेटा को पुनः प्राप्त करें (_firstComponentService.retrieveData ()) ngOnInit () में दूसराComponent

हालांकि यह दृष्टिकोण पूरी तरह से व्यवहार्य लगता है, मुझे आश्चर्य है कि क्या यह लक्ष्य प्राप्त करने का सबसे आसान / सबसे सुंदर तरीका है।

सामान्य तौर पर मैं यह जानना चाहूंगा कि क्या मैं घटकों के बीच डेटा पारित करने के लिए अन्य संभावित दृष्टिकोणों को याद कर रहा हूं , विशेष रूप से कोड की कम संभव राशि के साथ


6
मार्ग के माध्यम से डेटा साझा करने के 3 सरल तरीके - angulartutorial.net/2017/12/12/…
Prashobh

2
धन्यवाद @Prashobh Pass data using Query Parametersजिसकी मुझे तलाश थी वह है। आपके लिंक ने मेरा दिन बचाया।
राज

कोणीय 7.2 का उपयोग कर मार्गों के बीच डेटा पास करने के लिए अब नई सुविधा है stateजाँच पीआर अधिक जानकारी के लिए। यहाँ
AzizKapProg

@Prashobh बहुत बहुत धन्यवाद। आपके द्वारा साझा किया गया लिंक बहुत उपयोगी है
vandu

जवाबों:


193

4.0.0 अपडेट करें

अधिक जानकारी के लिए कोणीय डॉक्स देखें https://angular.io/guide/router#fetch-data-before-avavating

मूल

किसी सेवा का उपयोग करने का तरीका है। रूट परिमों में आपको केवल वह डेटा पास करना चाहिए जिसे आप ब्राउज़र URL बार में प्रतिबिंबित करना चाहते हैं।

Https://angular.io/docs/ts/latest/cookbook/component-communication.html#! #Bidirectional-service भी देखें

RC.4 के साथ राउटर ने पुनः परिचय दिया data

constructor(private route: ActivatedRoute) {}
const routes: RouterConfig = [
  {path: '', redirectTo: '/heroes', pathMatch : 'full'},
  {path : 'heroes', component : HeroDetailComponent, data : {some_data : 'some value'}}
];
class HeroDetailComponent {
  ngOnInit() {
    this.sub = this.route
      .data
      .subscribe(v => console.log(v));
  }

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

पर यह भी देखें Plunker https://github.com/angular/angular/issues/9757#issuecomment-229847781


4
क्या यह उत्तर अभी भी एंगुलर 2.1.0 के लिए मान्य है?
स्मार्टमाउस

9
RC.4 राउटर डेटा केवल स्थैतिक डेटा के लिए है। आप एक ही मार्ग पर अलग-अलग डेटा नहीं भेज सकते हैं यह हमेशा वही डेटा होना चाहिए जो मैं गलत हूं?
aycanadal

1
नहीं, इस उपयोग के मामले के लिए एक साझा सेवा का उपयोग करें।
गुंटर ज़ोचौएर

8
कोणीय 5 में, वैसे भी, आपको सक्षम होना चाहिए ... ngOnInit() { this.myVar = this.route.snapshot.data['some_data']; }
रोजर

5
यदि आप कोणीय v7.2 का उपयोग करने में सक्षम हैं, तो यह राउटर में अब स्टेट पास करने की अनुमति देता है NavigationExtras- stackoverflow.com/a/54879389/1148107
mtpultz

67

मुझे लगता है क्योंकि हमारे पास कोणीय 2 में $ rootScope तरह की चीज़ नहीं है जैसा कि कोणीय 1.x में है। हम ngOnDestroy पास डेटा को सेवा में रखने के दौरान कोणीय 2 साझा सेवा / वर्ग का उपयोग कर सकते हैं और रूटिंग के बाद ngOnInit फ़ंक्शन में सेवा से डेटा ले सकते हैं :

यहाँ मैं हीरो ऑब्जेक्ट शेयर करने के लिए डेटा सर्विस का उपयोग कर रहा हूँ:

import { Hero } from './hero';
export class DataService {
  public hero: Hero;
}

प्रथम पृष्ठ घटक से ऑब्जेक्ट पास करें:

 ngOnDestroy() {
    this.dataService.hero = this.hero; 
 }

दूसरे पृष्ठ घटक से वस्तु लें:

 ngOnInit() {
    this.hero = this.dataService.hero; 
 }

यहाँ एक उदाहरण है: प्लंकर


यह सुंदर है, लेकिन Ng2 समुदाय में यह कितना आम है? मैं इसे डॉक्स में पढ़ना याद नहीं कर सकता ...
अल्फा ब्रावो

1
यूआरएल विकल्प या अन्य ब्राउज़र स्टोरेज जैसे अन्य विकल्प की तुलना में यह मुझे बेहतर लगता है। मैंने इस तरह से काम करने के लिए किसी भी दस्तावेज में नहीं देखा।
उत्पल कुमार दास

2
क्या यह तब काम करता है जब उपयोगकर्ता एक नया टैब खोलता है और दूसरे घटक मार्ग को कॉपी पेस्ट करता है? क्या मैं लाने में सक्षम हो सकता हूं this.hero = this.dataService.hero? क्या मुझे मूल्य मिलेंगे?

यह वास्तव में बहुत सरल है और प्रत्येक कोणीय डेवलपर जानता है, लेकिन समस्या एक बार आप सेवाओं में ढीले डेटा को ताज़ा करने के लिए है। उपयोगकर्ता को फिर से सभी सामान करना होगा।
संतोष कदम

@SantoshKadam का सवाल है "मैं डेटा को एंगुलर रूट किए गए घटकों को कैसे पास करूं?" तो ngOnDestroy और ngOnInit फ़ंक्शन द्वारा डेटा पास करना एक तरीका है, और हमेशा सरल सबसे अच्छा है। यदि उपयोगकर्ता को पुनः लोड करने के बाद डेटा प्राप्त करने की आवश्यकता होती है तो स्थायी भंडारण में डेटा को बचाने और फिर से उस संग्रहण से पढ़ने की आवश्यकता होती है।
उत्पल कुमार दास

28
<div class="button" click="routeWithData()">Pass data and route</div>

अच्छी तरह से इसे कोणीय 6 या अन्य संस्करणों में करने का सबसे आसान तरीका है, मुझे आशा है कि आप अपने डेटा को उस मात्रा के साथ परिभाषित करना चाहते हैं जिसे आप पास करना चाहते हैं

{path: 'detailView/:id', component: DetailedViewComponent}

जैसा कि आप मेरे मार्गों की परिभाषा से देख सकते हैं, मैंने /:idराउटर नेविगेशन के माध्यम से उस घटक को डेटा में जोड़ने के लिए जोड़ा है जिसे मैं घटक को पास करना चाहता हूं। इसलिए आपका कोड दिखेगा

<a class="btn btn-white-view" [routerLink]="[ '/detailView',list.id]">view</a>

आदेश को पढ़ने के लिए में idघटक पर, बस आयात ActivatedRoute की तरह

import { ActivatedRoute } from '@angular/router'

और वह जगह ngOnInitहै जहाँ आप डेटा पुनः प्राप्त करते हैं

ngOnInit() {
       this.sub = this.route.params.subscribe(params => {
        this.id = params['id'];
        });
        console.log(this.id);
      }

आप इस लेख में और अधिक पढ़ सकते हैं https://www.tektutorialshub.com/angular-passing-parameters-to-route/


12
क्या होगा यदि मैं एक जटिल वस्तु भेजना चाहता हूं? मैं अपने मार्गों को
अकारण

@cmxl एक साझा सेवा का उपयोग करें।
स्टैनिस्लासड्रैग मोनिका

ठीक वही जो मेरे द्वारा खोजा जा रहा था। धन्यवाद!
अखिल

21

कोणीय घटकों के बीच नेविगेट करते समय कोणीय 7.2.0 ने डेटा पास करने का नया तरीका पेश किया:

@Component({
  template: `<a (click)="navigateWithState()">Go</a>`,
})
export class AppComponent  {
  constructor(public router: Router) {}
  navigateWithState() {
    this.router.navigateByUrl('/123', { state: { hello: 'world' } });
  }
}

या:

@Component({
  selector: 'my-app',
  template: `
  <a routerLink="/details" [state]="{ hello: 'world' }">Go</a>`,
})
export class AppComponent  {}

राज्य को पढ़ने के लिए, window.history.stateनेविगेशन समाप्त होने के बाद आप संपत्ति तक पहुँच सकते हैं:

export class PageComponent implements OnInit {
  state$: Observable<object>;

  constructor(public activatedRoute: ActivatedRoute) {}

  ngOnInit() {
    this.state$ = this.activatedRoute.paramMap
      .pipe(map(() => window.history.state))
  }
}

4
मेरे लिए काम नहीं करता है, मेरे द्वारा पारित वस्तु को वापस करने के बजाय window.history.stateकुछ लौटाता है {navigationId: 2}
लुई

@ कौन से कोणीय संस्करण का उपयोग कर रहे हैं?
वाशिंगटन सोरेस ब्रागा

मैं
लुई

मैं लुई के रूप में एक ही चीज देख रहा हूं, उसकी तुलना में कम संस्करण के साथ लेकिन अभी भी बहुत अधिक है कि यह उस सुविधा के लिए माना जाता है।
विंडोजविनी

लौटी हुई वस्तु के हिस्से के रूप में, navigationIdएक मूल्य के साथ जोड़ा जाता है। यदि कोई डेटा नहीं जोड़ा जाता है, तो केवल navigationIdदिखाया जाएगा। पास किए गए डेटा को देखें, वापस जाएं या अपने ऐप को रिफ्रेश करें और उस एक्शन को फिर से ट्रिगर करें जो डेटा को रूट में जोड़ता है और अगले रूट पर नेविगेट करता है (जैसे। बटन क्लिक)। यह तब आपके डेटा को ऑब्जेक्ट में जोड़ देगा।
अल्फ मो।

12

कुछ सुपर स्मार्ट व्यक्ति (tmburnell) जो मुझे मार्ग डेटा को फिर से लिखने का सुझाव नहीं देते हैं:

let route = this.router.config.find(r => r.path === '/path');
route.data = { entity: 'entity' };
this.router.navigateByUrl('/path');

जैसा कि यहां टिप्पणियों में देखा गया है

मुझे आशा है कि किसी को यह उपयोगी लगेगा


7
अभी इस बारे में पता चला है और मुझे ऐसा लग रहा है कि मुझे कुछ
स्टैकओवरफ्लो

11

मैं इस मुद्दे के लिए अन्य दृष्टिकोण अच्छा नहीं हूं। मुझे लगता है कि सबसे अच्छा दृष्टिकोण कोणीय -पैरामीटर है Routerकोणीय द्वारा 2 रास्ता है:

सीधे क्वेरी पैरामीटर पास करना

इस कोड के साथ आप पर नेविगेट कर सकते urlद्वारा paramsआपके HTML कोड में:

<a [routerLink]="['customer-service']" [queryParams]="{ serviceId: 99 }"></a>

द्वारा क्वेरी पैरामीटर पास करना Router

आपको अपने constructorपसंद के अनुसार राउटर को इंजेक्ट करना होगा :

constructor(private router:Router){

}

अब इस तरह का उपयोग करें:

goToPage(pageNum) {
    this.router.navigate(['/product-list'], { queryParams: { serviceId: serviceId} });
}

अब यदि आप Routerदूसरे से पढ़ना चाहते हैं तो आपको Componentइसका उपयोग करना होगा ActivatedRoute:

constructor(private activateRouter:ActivatedRouter){

}

और subscribe:

  ngOnInit() {
    this.sub = this.route
      .queryParams
      .subscribe(params => {
        // Defaults to 0 if no query param provided.
        this.page = +params['serviceId'] || 0;
      });
  }

this.router.navigate (['/ उत्पाद-सूची'], {queryParams: {serviceId: serviceId}}); इस के साथ प्रतिस्थापित किया जा सकता है। nterter.navigate (['/ उत्पाद-सूची'], {queryParams: {serviceId}});
रमाकांत सिंह

10

यह 2019 है और यहां के कई जवाब काम करेंगे, जो आप करना चाहते हैं उसके आधार पर। यदि आप कुछ आंतरिक स्थिति में पास होना चाहते हैं जो URL (params, query) में दिखाई नहीं दे रहा है, तो आप state7.2 (जैसा कि मैंने सीखा है ) का उपयोग कर सकते हैं है :))।

ब्लॉग से (क्रेडिट टॉमस कुला) - आप रूट पर नेविगेट करते हैं ...।

... ts से: this.router.navigateByUrl('/details', { state: { hello: 'world' } });

... HTML टेम्पलेट से: <a routerLink="/details" [state]="{ hello: 'world' }">Go</a>

और लक्ष्य घटक में इसे लेने के लिए:

constructor(public activatedRoute: ActivatedRoute) {}

  ngOnInit() {
    this.state$ = this.activatedRoute.paramMap
      .pipe(map(() => window.history.state))
  }

देर से, लेकिन आशा है कि यह किसी को हाल ही में कोणीय के साथ मदद करता है।


6

ActiveRoute के साथ समाधान (यदि आप मार्ग से ऑब्जेक्ट पास करना चाहते हैं - JSON.stringfy / JSON.parse का उपयोग करें):

भेजने से पहले वस्तु तैयार करें:

export class AdminUserListComponent {

  users : User[];

  constructor( private router : Router) { }

  modifyUser(i) {

    let navigationExtras: NavigationExtras = {
      queryParams: {
          "user": JSON.stringify(this.users[i])
      }
    };

    this.router.navigate(["admin/user/edit"],  navigationExtras);
  }

}

गंतव्य घटक में अपनी वस्तु प्राप्त करें:

export class AdminUserEditComponent  {

  userWithRole: UserWithRole;      

  constructor( private route: ActivatedRoute) {}

  ngOnInit(): void {
    super.ngOnInit();

      this.route.queryParams.subscribe(params => {
        this.userWithRole.user = JSON.parse(params["user"]);
      });
  }

}

1
यह काम करता है, लेकिन क्या होगा अगर मैं URL के सभी डेटा को उजागर नहीं करना चाहता?
mpro

आप टारगेट कंपोनेंट में एनक्रिप्ट करने के बाद डेटा को परमेस में डाल सकते हैं।
बिच्छू

मैंने डेटा साझा करने के लिए सेवा बनाई है
एमप्रो

वह किस super.ngOnInit();लिए है?
एंड्रिया घेरार्डी

5

घटकों के बीच डेटा साझा करने के लिए तीसरा तरीका सबसे आम तरीका है। आप संबंधित घटक में जिस आइटम सेवा का उपयोग करना चाहते हैं उसे इंजेक्ट कर सकते हैं।

import { Injectable } from '@angular/core';
import { Predicate } from '../interfaces'

import * as _ from 'lodash';

@Injectable()
export class ItemsService {

    constructor() { }


    removeItemFromArray<T>(array: Array<T>, item: any) {
        _.remove(array, function (current) {
            //console.log(current);
            return JSON.stringify(current) === JSON.stringify(item);
        });
    }

    removeItems<T>(array: Array<T>, predicate: Predicate<T>) {
        _.remove(array, predicate);
    }

    setItem<T>(array: Array<T>, predicate: Predicate<T>, item: T) {
        var _oldItem = _.find(array, predicate);
        if(_oldItem){
            var index = _.indexOf(array, _oldItem);
            array.splice(index, 1, item);
        } else {
            array.push(item);
        }
    }


    addItemToStart<T>(array: Array<T>, item: any) {
        array.splice(0, 0, item);
    }


    getPropertyValues<T, R>(array: Array<T>, property : string) : R
    {
        var result = _.map(array, property);
        return <R><any>result;
    }

    getSerialized<T>(arg: any): T {
        return <T>JSON.parse(JSON.stringify(arg));
    }
}



export interface Predicate<T> {
    (item: T): boolean
}

3
मार्ग स्विच करते समय सेवा तुरंत हो जाती है। तो आप डेटा ढीला
जिमी केन

1
@JimmyKane आप विशेष रूप से उस समय के बारे में बोल रहे हैं जब पृष्ठ ताज़ा हो जाता है, लेकिन यदि यह ताज़ा नहीं होता है, तो मेमोरी अभी भी एक सेवा में सहेजी जाती है। यह डिफ़ॉल्ट व्यवहार होना चाहिए क्योंकि यह कई बार लोड करने से बचाएगा।
एरोन राबिनोविट्ज़

1
@AaronRabinowitz सही। गलतफहमी के लिए खेद है। और डाउन वोट के लिए खेद है। काश मैं इसे अब पूर्ववत कर सकता। बहुत देर। कोणीय 2 के लिए नया था और आपके दृष्टिकोण की कोशिश करने में मेरी समस्या यह थी कि मेरे पास कई घटकों को प्रदान की गई सेवा थी और ऐप मॉड्यूल के माध्यम से प्रदान नहीं की गई थी।
जिमी केन

3

JSON का उपयोग करके पास करें

  <a routerLink = "/link"
   [queryParams] = "{parameterName: objectToPass| json }">
         sample Link                   
  </a>

7
यह एक बेहतर उत्तर होगा यदि आप दिखा सकते हैं कि प्राप्त घटक में पैरामीटर का उपभोग कैसे किया जाता है - पूरे मार्ग जो इसे लेता है। मतलब अगर कोई नहीं जानता कि कैसे एक पैरामीटर पास करना है, तो वह यह भी नहीं जान सकता है कि प्राप्त पैरामीटर में इस पैरामीटर का उपयोग कैसे किया जाए। :)
अल्फा ब्रावो

इसका एक नुकसान यह है कि क्वेरिस्ट्रिंग के लिए एक आकार सीमा है और कभी-कभी आप पता बार में दिखाई देने वाले ऑब्जेक्ट गुण नहीं चाहते हैं।
CM

3

कस्टम इंडेक्स के साथ डेटा स्टोर करने के लिए एक साझा सेवा का उपयोग करें। फिर उस कस्टम इंडेक्स को queryParam के साथ भेजें। यह दृष्टिकोण अधिक लचीला है

// component-a : typeScript :
constructor( private DataCollector: DataCollectorService ) {}

ngOnInit() {
    this.DataCollector['someDataIndex'] = data;
}

// component-a : html :
<a routerLink="/target-page" 
   [queryParams]="{index: 'someDataIndex'}"></a>

// component-b : typeScript :
public data;

constructor( private DataCollector: DataCollectorService ) {}

ngOnInit() {
    this.route.queryParams.subscribe(
        (queryParams: Params) => {
            this.data = this.DataCollector[queryParams['index']];
        }
    );
}

0

आप कहें

  1. component1.ts
  2. component1.html

और आप डेटा को कंपोनेंट 2 के पास करना चाहते हैं

  • कंपोनेंट 1 में एक डेटा वेरिएंट के साथ एक वेरिएंट है

      //component1.ts
      item={name:"Nelson", bankAccount:"1 million dollars"}
    
      //component1.html
       //the line routerLink="/meter-readings/{{item.meterReadingId}}" has nothing to 
      //do with this , replace that with the url you are navigating to
      <a
        mat-button
        [queryParams]="{ params: item | json}"
        routerLink="/meter-readings/{{item.meterReadingId}}"
        routerLinkActive="router-link-active">
        View
      </a>
    
      //component2.ts
      import { ActivatedRoute} from "@angular/router";
      import 'rxjs/add/operator/filter';
    
      /*class name etc and class boiler plate */
      data:any //will hold our final object that we passed 
      constructor(
      private route: ActivatedRoute,
      ) {}
    
     ngOnInit() {
    
     this.route.queryParams
      .filter(params => params.reading)
      .subscribe(params => {
      console.log(params); // DATA WILL BE A JSON STRING- WE PARSE TO GET BACK OUR 
                           //OBJECT
    
      this.data = JSON.parse(params.item) ;
    
      console.log(this.data,'PASSED DATA'); //Gives {name:"Nelson", bankAccount:"1 
                                            //million dollars"}
       });
      }

0

आप रूट किए गए घटकों के बीच डेटा साझा करने के लिए BehaviorSubject का उपयोग कर सकते हैं। एक BehaviorSubject एक मूल्य रखता है। जब इसे सब्सक्राइब किया जाता है तो यह तुरंत मूल्य का उत्सर्जन करता है। एक विषय एक मूल्य नहीं रखता है।

सेवा में।

@Injectable({
  providedIn: 'root'
})
export class CustomerReportService extends BaseService {
  reportFilter = new BehaviorSubject<ReportFilterVM>(null);
  constructor(private httpClient: HttpClient) { super(); }

  getCustomerBalanceDetails(reportFilter: ReportFilterVM): Observable<Array<CustomerBalanceDetailVM>> {
    return this.httpClient.post<Array<CustomerBalanceDetailVM>>(this.apiBaseURL + 'CustomerReport/CustomerBalanceDetail', reportFilter);
  }
}

घटक में आप इस BehaviorSubject की सदस्यता ले सकते हैं।

this.reportService.reportFilter.subscribe(f => {
      if (f) {
        this.reportFilter = f;
      }
    });

नोट: विषय यहाँ काम नहीं करेगा, केवल व्यवहार विषय का उपयोग करने की आवश्यकता है।

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