简体   繁体   中英

How to pass value from a service to a parent component

i have a parent component and a service. i want to pass the value of the variable

mMeasuredDistanceInKM

to the main component. therefore i created an output variable in the service as follows

@Output() EventEmittermMeasuredDistanceInKM: EventEmitter<string>= new EventEmitter();

now i want to access the emitted value from

@Output() EventEmittermMeasuredDistanceInKM

in the main component. how can i do that while the service do not have a template

code :

<button class="btn btn-sm btn-icon"  data-title= {{}} (click)="editTopography()" data-tooltip="text"> <clr-icon shape="pencil"></clr-icon></button>

apiservice :

import { Injectable, Output, EventEmitter } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class ApiService {
  API_KEY = '5b3ce3597845532301cf62480erve403567479a87de01df5da651gy';

  mResponseAsJSON;
  mMeasuredDistance;
  mMeasuredDistanceInKM;

  @Output() EventEmittermMeasuredDistanceInKM: EventEmitter<string>= new EventEmitter();
  constructor(private httpClient: HttpClient) { }

  public getDistanceBetweenCoordinates(lng1,lat1,lng2, lat2) {

    return this.httpClient.get(
      "https://api.openrouteservice.org/v2/directions/driving-car?api_key=5b3ce3597845532301cf62480erve403567479a87de01df5da651gy&start="+ lng1+"," + lat1+ "&end="+lng2+","+lat2)
      .subscribe((data)=>{
        this.mResponseAsJSON = data;
        this.mMeasuredDistance = data["features"][0]['properties']['summary']['distance'];
        this.mMeasuredDistanceInKM = this.mMeasuredDistance/1000;
        this.EventEmittermMeasuredDistanceInKM.emit(this.mMeasuredDistanceInKM)
        console.log("DistanceBetweenGivenCoordinates = " + this.mMeasuredDistanceInKM + " Km");
    });
} 
}

The @Output and @Input directives are only for Components . In order to exchange data between components via a service you have to use Dependency Injection .

So in both your Components you have to inject your Service:
constructor(private apiService: ApiService)

Since your data is coming asynchronous via the httpClient, you will have to use the Observable in your components. Instead of subscribing to it in your service and returning the subscription you can return the observable itself and subscribe to it in your components.

// your service method:
public getDistanceBetweenCoordinates(lng1,lat1,lng2, lat2) {
  return this.httpClient.get("https://api.openrouteservice.org/v2/directions/driving-car?api_key=5b3ce3597845532301cf62480erve403567479a87de01df5da651gy&start="+ lng1+"," + lat1+ "&end="+lng2+","+lat2);
}

// somewhere in your component:
this.apiService.getDistanceBetweenCoordinates(lng1, lat1, lng2, lat2).subscribe((data) => {
  // now you have the data in your components
})

If you want to use or alter the data in the service before the component receives it you can make use of rxjs operators , like tap or map :

public getDistanceBetweenCoordinates(lng1,lat1,lng2, lat2) {

    return this.httpClient.get(
      "https://api.openrouteservice.org/v2/directions/driving-car?api_key=5b3ce3597845532301cf62480erve403567479a87de01df5da651gy&start="+ lng1+"," + lat1+ "&end="+lng2+","+lat2)
      .pipe(map(data) => {
        // to just get the "measuredDistanceInKM" in the subscribe:
        return data["features"][0]['properties']['summary']['distance']/1000;
      })
} 

@Output() will help you to pass data and use event emitter in such cases;

@Output() methodName = new EventEmitter<any>();

you can refer this Component interaction link in Angular

apiservice

import { Injectable, Output, EventEmitter } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class ApiService {
  API_KEY = '5b3ce3597845532301cf62480erve403567479a87de01df5da651gy';

  mResponseAsJSON;
  mMeasuredDistance;
  mMeasuredDistanceInKM;

  EventEmittermMeasuredDistanceInKM_changed = new EventEmitter<string>();
  
  constructor(private httpClient: HttpClient) { }

  public getDistanceBetweenCoordinates(lng1,lat1,lng2, lat2) {

    return this.httpClient.get(
      "https://api.openrouteservice.org/v2/directions/driving-car?api_key=5b3ce3597845532301cf62480erve403567479a87de01df5da651gy&start="+ lng1+"," + lat1+ "&end="+lng2+","+lat2)
      .subscribe((data)=>{
        this.mResponseAsJSON = data;
        this.mMeasuredDistance = data["features"][0]['properties']['summary']['distance'];
        this.mMeasuredDistanceInKM = this.mMeasuredDistance/1000;
        this.EventEmittermMeasuredDistanceInKM_changed.emit(this.mMeasuredDistanceInKM)
        console.log("DistanceBetweenGivenCoordinates = " + this.mMeasuredDistanceInKM + " Km");
    });
} 
}

main component.ts
in any component where you need to subscribe the changes in the emitted value you need to inject it as shown below

EventEmittermMeasuredDistanceInKM_subscription:Subscription;
EventEmittermMeasuredDistanceInKM : string;


  constructor(private apiser:apiservice) { }
    
    
  ngOnInit(): void {
      
      this.EventEmittermMeasuredDistanceInKM_subscription = this.apiser.EventEmittermMeasuredDistanceInKM_changed.subscribe((EventEmittermMeasuredDistanceInKM)=>{
      this.EventEmittermMeasuredDistanceInKM = EventEmittermMeasuredDistanceInKM;
    })

  }

do not forget to unsubscribe the 'EventEmittermMeasuredDistanceInKM_subscription'
just for the information It is Recommended to use Subject Instead of EventEmitter

html
as you said in comment its showing undefined you may use async pipe to wait for the response.

<h3>{{ EventEmittermMeasuredDistanceInKM | async  }}</h3>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM