user5368536
user5368536

Reputation:

Angular 8: ERROR TypeError: Cannot read property 'toLowerCase' of undefined

I'm getting ERROR TypeError: Cannot read property 'toLowerCase' of undefined every time when I'm trying to log my api result in the browser. Here is my service class

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

    @Injectable({
      providedIn: 'root'
    })
    export class GetlocationService {
      lat:any='';
      long:any='';
      url:any='';
      weatherUrl:any='';


      constructor(private http:HttpClient) {

        if(navigator.geolocation)
        {

          navigator.geolocation.getCurrentPosition( position=>
          {

            this.lat = position.coords.latitude;
            this.long = position.coords.longitude;
            this.url =`https://us1.locationiq.com/v1/reverse.php?key=[mykey]&lat=${this.lat}&lon=${this.long}&format=json`;

            this.weatherUrl=`https://cors-anywhere.herokuapp.com/https://api.darksky.net/forecast/[mykey]/${this.lat},${this.long}`;

          })
        }
      }

     public getLocationName()
      {

        return this.http.get(this.url);
      }

      public getWeather()
      {
        return this.http.get(this.weatherUrl);

      }

    }

and here is my locationweather component from where I'm calling my service.

    import { Component, OnInit } from '@angular/core';
    import { GetlocationService } from '../getlocation.service';
    import { getLocaleDateFormat } from '@angular/common';

    @Component({
      selector: 'app-locationweather',
      templateUrl: './locationweather.component.html',
      styleUrls: ['./locationweather.component.css']
    })
    export class LocationweatherComponent implements OnInit {

      constructor( private getLocation:GetlocationService) { }


      locations:any=[];
      weathers:any=[];
      getLocationDetail()
        {
          this.getLocation.getLocationName().subscribe((data:any)=> 
          {
           console.log(data)
           this.locations.push(data);
          })
        }

        getWeatherDetails()
        {

          this.getLocation.getWeather().subscribe((weather:any)=>
            {

              console.log(weather)
              this.weathers.push(weather)

            })
        }

        focusClear(add)
        {
          add.value="";

        }

        ngOnInit() {
          // this.getLocationDetail();
          this.getWeatherDetails()

        }
    }

Can anyone please help me? I'm calling service in ngOnit because I need them whenever my page loads.

PS. I just started learning angular and trying to put my knowledge I gained so far in this mini project.

EDIT:After assigning empty string to long, lat, url and weatherUrl, I no more see the Angular 8: ERROR TypeError: Cannot read property 'toLowerCase' of undefinedin the console. Now I'm getting ERROR HttpErrorResponse {headers: HttpHeaders, status: 200, statusText: "OK", url: "http://localhost:4200/", ok: false, …} in the console.

Upvotes: 1

Views: 2349

Answers (1)

ic_paty
ic_paty

Reputation: 432

Could you please check the values of the attributes this.lat and this.long before calling weather and location urls? by printing them in the console.

   public getLocationName() {
    console.log(this.lat);
    console.log(this.long);
    return this.http.get(this.url);
  }

  public getWeather() {
    return this.http.get(this.weatherUrl);

  }

Seems that you need also an access key to access the apis weather and location as mentionned in the urls [myKey]

Try also to test weather and location urls by testing them directlty on the navigator with real values for (lat, long and key) to make sure that they are correct.

Edit:

Can you check if you are getting an error while calling navigator.geolocation.getCurrentPosition method by catching the error as mentionned in the code below:

if (navigator.geolocation) {

  navigator.geolocation.getCurrentPosition(position => {
    console.log('here');
    this.lat = position.coords.latitude;
    this.long = position.coords.longitude;

  },
    error => {
      console.log('-----------------ERROR:--------------');
      console.log(error);
    }
  );

}

Second Edit:

Got it, navigator.geolocation.getCurrentPosition needs to be finished before calling both methods getLocationName & getWeather that those 2 methods depends on the output of the previous method. So what you need to to do is to wait for asynchronous methods to finish using basic promises with async/await. Here is a working example:

GetLocation Service

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

@Injectable({
  providedIn: 'root'
})
export class GetlocationService {
  private lat: any = '';
  private long: any = '';
  url: any = '';
  weatherUrl: any = '';


  constructor(private http: HttpClient) {
  }


  public async initialize() {
    await this.getPosition().then(pos => {
      this.lat = pos.lat;
      this.long = pos.lng;
      console.log(`Positon: ${pos.lng} ${pos.lat}`);
    });
  }

  public getPosition(): Promise<any> {
    return new Promise((resolve, reject) => {
      navigator.geolocation.getCurrentPosition(resp => {
        resolve({ lng: resp.coords.longitude, lat: resp.coords.latitude });
      },
        err => {
          reject(err);
        });
    });

  }

  public getLocationName() {
    console.log('location method :' + this.lat);
    console.log('location method:' + this.long);
    this.url = ''; //update url
    return this.http.get(this.url);

  }

  public getWeather() {
    console.log('weather method:' + this.lat);
    console.log('weather method:' + this.long);
    this.weatherUrl = ''; //update weather url
    return this.http.get(this.weatherUrl);
  }
}

Component TS

import { Component, OnInit } from '@angular/core';
import { GetlocationService } from './location.service';

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

  constructor(private getLocation: GetlocationService) { }


  locations: any = [];
  weathers: any = [];
  getLocationDetail() {
    this.getLocation.getLocationName().subscribe((data: any) => {
      console.log(data)
      this.locations.push(data);
    })
  }

  getWeatherDetails() {
    this.getLocation.getWeather().subscribe((weather: any) => {
      console.log(weather)
      this.weathers.push(weather)

    })
  }

  focusClear(add) {
    add.value = "";

  }

  async ngOnInit() {
    await this.getLocation.initialize();
    this.getLocationDetail();
    this.getWeatherDetails()

  }
}

Hope it helps!

Upvotes: 2

Related Questions