0

So I figuring out my way around Angular. Just started with a OpenWeather API based application using a simple GET method.

So here is my app.component.ts:

import { Component } from '@angular/core';
import { WeatherService } from './weather.service';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  providers: [WeatherService]
})
export class AppComponent {
  title = 'Ng-Weather';
  cityName: string;    
  constructor(private weather: WeatherService) { }    
  search() {
    this.weather.getWeatherbyName(this.cityName);
  }
}

As you can guess, the cityName variable is two way binded. The search() function is invoked onclick of a button and the data is passed to the weatherservice. The contents of weather service is:

import { Injectable } from '@angular/core';
import { Http, Response, URLSearchParams } from '@angular/http';
import { Observable } from 'rxjs';
import { Weather } from './weather';
@Injectable()
export class WeatherService {
  APIurl = "http://api.openweathermap.org/data/2.5/weather";
  Appid = "xxx";
  constructor(private Http: Http) { }
  getWeatherbyName(name: string): Observable<any> {
    let myParams = new URLSearchParams();
    myParams.append('q', name);
    myParams.append('appid', this.Appid);
    // actual http request should look like this: http://api.openweathermap.org/data/2.5/weather?appid=xxx&q=Chennai
    return this.Http.get(this.APIurl, { search: myParams})
      .map(this.extractData)
      .catch(this.handleError);
  }
  private extractData(res: Response) {
    console.log(res.json());
    let body = res.json();
    return body.data;
  }
  private handleError(error: Response | any) {
    console.error(error.message || error);
    return Observable.throw(error.message || error);
  }
}

But I get no error in my console or during the compile process. What is being done wrong? Also, how can I map the JSON I get to my class and give back that instance to the app.component?

Following is my class:

export class Weather {
    city: String;
    max_temp: String;
    min_temp: String;
    description: String;
}

And this is a sample JSON I receive:

{  
    "coord":{  
        "lon":80.28,
        "lat":13.09
    },
    "weather":[  
        {  
            "id":803,
            "main":"Clouds",
            "description":"broken clouds",
            "icon":"04n"
        }
    ],
    "base":"stations",
    "main":{  
        "temp":304.15,
        "pressure":1008,
        "humidity":79,
        "temp_min":304.15,
        "temp_max":304.15
    },
    "visibility":6000,
    "wind":{  
        "speed":3.1,
        "deg":160
    },
    "clouds":{  
        "all":75
    },
    "dt":1504629000,
    "sys":{  
        "type":1,
        "id":7834,
        "message":0.0029,
        "country":"IN",
        "sunrise":1504571272,
        "sunset":1504615599
    },
    "id":1264527,
    "name":"Chennai",
    "cod":200
}

As you can see all I need is some data from the JSON and not the whole thing.

4
  • if you look in the network tab of the chrome debugger, what does the url request to openweathermap look like? Commented Sep 5, 2017 at 18:22
  • it never sends a request actually thats the biggest pain. I tried this return this.Http.get('http://api.openweathermap.org/data/2.5/weather?appid=xxx&q=' + name) .map(this.extractData) .catch(this.handleError); still nothing in network log or console. Commented Sep 5, 2017 at 18:26
  • For your map result, you can create an interface of what you need, and create a new object (of this interface), in which you bind your wanted properties with the returned result. Look at the destructuring operator from ES6 : developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Commented Sep 5, 2017 at 18:36
  • @JackSlayer94 have u tried using {params: myParams} instead? Commented Sep 5, 2017 at 18:53

2 Answers 2

2

Your main problem here is that you are not subscribing to the observable that is being produced by your getWeatherbyName function. Observables returned by Http are cold:

Cold observables start running upon subscription, i.e., the observable sequence only starts pushing values to the observers when Subscribe is called. (…) This is different from hot observables such as mouse move events or stock tickers which are already producing values even before a subscription is active.

In order to subscribe to this observable, you can simply update your search function to the following:

search() {
    this.weather.getWeatherbyName(this.cityName)
        .subscribe();
}

This is by no means the complete solution to your problem - You will want to do something in the subscription, such as assign the information received to properties of your component so that they can be rendered in the UI.

You appear to have other issues in your linked project, but I suggest you ask separate questions on Stack Overflow if needed, or even better, your favorite search engine should be able to help.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the pointers! Basically what I was doing in my constructor was using Http: Http so when I was performing a request, it referred to the Angular class and not the local instance. Changing from constructor(private Http: Http) { } to constructor(private http: Http) { } and also return this.Http.get(this.APIurl, { search: myParams}) to return this.http.get(this.APIurl, { search: myParams}) made it work!
1

Try passing a RequestOptions object to the http get instead:

import { RequestOptions } from '@angular/http';    

getWeatherbyName(name: string): Observable<any> {
            let myParams = new URLSearchParams();
            myParams.append('q', name);
            myParams.append('appid', this.Appid);

            let options = new RequestOptions({ search: myParams}); //<----- NEW

            // actual http request should look like this: http://api.openweathermap.org/data/2.5/weather?appid=xxx&q=Chennai
            return this.Http.get(this.APIurl, options) //<<----- NEW
              .map(this.extractData)
              .catch(this.handleError);
          }

1 Comment

@JackSlayer94 you can use HttpClientModule instead of httpclient in your app module and then you can do let params = new HttpParams() .set('DataTable', 'tablename') .set('pageSize', '-1'); this.http .get(baseUrl, { params}) .do(val => console.log(val)) in your service.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.