0

I'm currently working with the OpenWeatherMap API (https://openweathermap.org/current) and I'm trying to get main.temp, main.feels_like, main.temp_min and main.temp_max fields of the Observable which I get from an HTTP request.

It's possible for me to get all the data, but I only need these fields. How do I get these fields and put them in my own variables?

import {Component, OnInit} from '@angular/core';
import {WeatherServiceService} from "./Services/weather-service.service";
import {LocationData} from "./models/location-data";
import {HttpClient} from "@angular/common/http";
import {Observable} from "rxjs";

declare const L: any
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit{

data!:LocationData
location!:string
locationData = new LocationData();

constructor(public weatherService:WeatherServiceService, public http: HttpClient) {
}

ngOnInit() {
if (!navigator.geolocation){
  console.log("location is not supported")
}
navigator.geolocation.getCurrentPosition((position) => {
  const coords = position.coords
  const latLong = [coords.latitude, coords.longitude]
  console.log(
    'lat: ${position.coords.latitude}, lon: ${position.coords.longitude}'
  );
  let mymap = L.map('map').setView(latLong, 13);

  L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}? access_token=pk.eyJ1Ijoia29lbnRlcmhlZWdkZSIsImEiOiJja3NpejZibWsxcGFhMzBvZjRlOXhkcWZoIn0.Bs552hPcijlBy1b2kDqfvw', {
    attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
    maxZoom: 18,
    id: 'mapbox/streets-v11',
    tileSize: 512,
    zoomOffset: -1,
    accessToken: 'your.mapbox.access.token'
  }).addTo(mymap);

  let marker = L.marker(latLong).addTo(mymap);
});
this.watchPosition();
}

watchPosition(){
let desLat = 0;
let desLon = 0;
let id = navigator.geolocation.watchPosition(position => {
  console.log(
    'lat: ${position.coords.latitude}, lon: ${position.coords.longitude}'
  );
  if (position.coords.latitude === desLat && position.coords.longitude === desLon){
    navigator.geolocation.clearWatch(id);
  }
}, (err) => {
  console.log(err);
}, {
  enableHighAccuracy: false,
  timeout: 5000,
  maximumAge: 0
})
}

getCoordinates(){

this.weatherService.getData().subscribe((data: LocationData) => this.locationData = {
  temp_min: data.temp_min,
  temp_max: data.temp_max,
  temp: data.temp,
  feels_like: data.feels_like
})

// this.weatherService.getData().subscribe(data => this.locationData = data)

// this.weatherService.getData().subscribe(res =>{
//   console.log(res)
// })



}

}

Interface:

import { Injectable } from '@angular/core';
import {HttpClient} from "@angular/common/http";
import { Observable, throwError } from 'rxjs';
import { catchError, retry } from 'rxjs/operators';
import {LocationData} from "../models/location-data";

@Injectable({
providedIn: 'root'
})
export class WeatherServiceService {

constructor(public http: HttpClient) {

}

getData() : Observable<LocationData>{
return this.http.get<LocationData>('http://api.openweathermap.org/data/2.5/weather?q=Enschede&appid=2a47a80c223baab80003883c31f35729')

}
}

Model:

export class LocationData {
temp!:number
feels_like!:number
temp_min!:number
temp_max!:number

}
MikeOne
  • 4,789
  • 2
  • 26
  • 23
  • Can you clarify what is blocking you or doesn't work? At 1st look you already have the whole code.. – Gaël J Aug 23 '21 at 18:29
  • He Koen from Enske (my town). You can map it directly in your service. Something like return this.http.get('http://api.openweathermap.org/data/2.5/weather?q=Enschede&appid=2a47a80c223baab80003883c31f35729').pipe(map( (data: any) => { return { temp_min: data.temp_min, temp_max: data.temp_max, temp: data.temp, feels_like: data.feels_like } )) – MikeOne Aug 23 '21 at 18:30
  • (Maybe missing some brackets there, I’m on mobile) – MikeOne Aug 23 '21 at 18:31
  • ..mm.. SO is truncating my comment. Next attempt: return this.http.get('http://api.openweathermap.org/data/2.5/weather?q=Enschede').pipe( map( (data: any) => { return {temp_min: data.temp_min, temp_max: data.temp_max, temp: data.temp, feels_like: data.feels_like} } ) ) – MikeOne Aug 23 '21 at 18:38
  • @GaëlJ If I print those values, they are all 'undefined' instead of the values it gives if I enter the link in the browser. – Koen ter Heegde Aug 23 '21 at 19:32
  • @MikeOne haha that's coincidental! If I add this code in my service, what do I put in my component typescript file? I would like to print out the values as well. – Koen ter Heegde Aug 23 '21 at 19:34
  • @KoenterHeegde It is! I see maury844 gave a fine answer. (PS: If you're ever stuck, feel free to ping me on Twitter @Dutch_Guy) – MikeOne Aug 23 '21 at 20:00
  • @MikeOne the code of maury844 isn't completely working yet! Do you know how to fix it? – Koen ter Heegde Aug 23 '21 at 20:06

1 Answers1

1

It seems like you have almost everything you need already, on your service you can map the response to get only the values you want, like this:

This is the structure of the json response:

json structure

getData() : Observable<LocationData>{
  const url = 'http://api.openweathermap.org/data/2.5/weather?q=Enschede&appid=2a47a80c223baab80003883c31f35729';
  return this.http.get(url).pipe(map((response: any) => ({
    temp: response.main.temp,     
    temp_min: response.main.temp_min, 
    temp_max: response.main.temp_max,
    feels_like: response.main.feels_like
  })))
}

and then you can just subscribe in your component

getCoordinates() {

  this.weatherService.getData().subscribe((data: LocationData) => {
    this.locationData = data;
  });

  // this.weatherService.getData().subscribe(res =>{
  //   console.log(res)
  // })
}
maury844
  • 1,210
  • 15
  • 25
  • 1
    Thanks for your answer! I'm using a newer version of RxJS so I have to use pipe(), otherwise the map() function doesn't work. I solved it like this [link](https://stackoverflow.com/questions/37208801/property-map-does-not-exist-on-type-observableresponse). This however gives me the error: 'Property 'main' does not exist on type 'Object'. How can I solve this? – Koen ter Heegde Aug 23 '21 at 20:00
  • ah right. return this.http.get(url)..pipe(map( (response: any) => ({ temp: response.main.temp, temp_min: response.main.temp_min, temp_max: response.main.temp_max, feels_like: response.main.feels_like }))) ..should do it.. – MikeOne Aug 23 '21 at 20:11
  • @MikeOne I get the same error again: Property 'map' does not exist on type 'Observable – Koen ter Heegde Aug 23 '21 at 20:17
  • Sorry - I missed the missing pipe - so that needs to be in (wrap it in a .pipe) - the trick for your Typescript error is to type the .get response as any. So (response: any) => – MikeOne Aug 23 '21 at 20:20
  • 2
    @MikeOne and maury844 Yes this works! Thank you so much, you are my heroes ;) – Koen ter Heegde Aug 23 '21 at 20:24
  • 1
    Excellent! Enjoy coding - Angular is fantastic! – MikeOne Aug 23 '21 at 20:26