I have my Angular 2 project that tries to get user's current location, therefore in my class I have the following code:
export class CurrentLocation {
constructor(private http: Http) { }
private lat : any;
private lon : any;
private params = new URLSearchParams();
private url = 'api/search/location';
getPosition = (lat, lon) => {
navigator.geolocation.getCurrentPosition((position) => {
this.lat = position.coords.latitude;
this.lon = position.coords.longitude;
});
}
getCurrentLocation(): Observable<any> {
this.getPosition(this.lat, this.lon);
console.log(this.lat+ "," + this.lon);
//console.log(this.lat + ":" + this.lon);
this.params.set('lat', this.lat);
this.params.set('lon', this.lon);
//console.log(this.params.toString());
var result = this.http.get(this.url, { search: this.params });
result.toPromise();
return result;
}
}
But lat
and lon
return undefined
.. The expected behaviour I want is once I got those latitude and longitude, I will send it to my backend address like following url http://localhost:8080/api/search/location?lat=123&lon=123
But it seems like setting value for lat
and lon
are failed.
How can I properly set the latitude and longitude in this class?
EDIT on August 3:
According libertyernie's answer below, I can successfully pass the current lat and lon into backend, but I don't know how to convert to Observable, since I try to using Table module in Angular Material, in that module for data source it must be Observable...
Here is the code after I try, but still not working...
import { Component, OnInit } from '@angular/core';
import { Http, Response, URLSearchParams } from '@angular/http';
import { DataSource } from '@angular/cdk';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/startWith';
import 'rxjs/add/observable/merge';
import 'rxjs/add/operator/map';
import { Restaurant } from '../restaurant/restaurant';
import { Category } from '../category/category';
import { RestaurantService } from '../restaurant/restaurant.service';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
displayedColumns = ['Id', 'Name', 'Category', 'Address', 'City'];
exampleDatabase: ExampleHttpDatabase | null;
dataSource: ExampleDataSource | null;
location: CurrentLocation | null;
lat: any;
lon: any;
result: Promise<any>;
constructor(http: Http) {
this.exampleDatabase = new ExampleHttpDatabase(http);
this.dataSource = new ExampleDataSource(this.exampleDatabase);
this.location = new CurrentLocation(http);
}
ngOnInit() {
this.result = this.location.getCurrentLocation(this.lat, this.lon);
this.result.then(function(result){
console.log(result._body);
})
console.log(this.lat, this.lon);
this.dataSource.connect();
}
}
export class ExampleHttpDatabase {
private restaurantUrl = 'api/restaurant'; // URL to web API
getRestaurants(): Observable<Restaurant[]> {
var result = this.http.get(this.restaurantUrl)
.map(this.extractData);
result.toPromise();
return result;
}
extractData(result: Response): Restaurant[] {
return result.json().map(restaurant => {
return {
id: restaurant.id,
name: restaurant.restaurant_name,
category: restaurant.category.map(c => c.categoryName).join(','),
address: restaurant.address.address,
city: restaurant.address.city.city_name
}
});
}
constructor(private http: Http) { }
}
export class CurrentLocation {
constructor(private http: Http) { }
private lat: any;
private lon: any;
private params = new URLSearchParams();
private url = 'api/search/location';
getPosition = () => {
var latitude, longitude;
return new Promise((resolve, reject) => {
navigator.geolocation.getCurrentPosition((position) => {
resolve(position.coords);
}, (err) => {
reject(err);
});
})
}
async getCurrentLocation(lat, lon): Promise<any> {
let coords = await this.getPosition();
lat = this.lat = coords['latitude'];
lon = this.lon = coords['longitude'];
this.params.set('lat', this.lat);
this.params.set('lon', this.lon);
var result = this.http.get(this.url, { search: this.params });
return await result.toPromise();
}
}
export class ExampleDataSource extends DataSource<Restaurant> {
constructor(private _exampleDatabase: ExampleHttpDatabase) {
super();
}
/** Connect function called by the table to retrieve one stream containing the data to render. */
connect(): Observable<Restaurant[]> {
return this._exampleDatabase.getRestaurants();
}
disconnect() { }
}
Sorry about the code is a little bit confusing.. But I don't know how to pass the result into connect()
function to make Material Table works..
Full code also in Github: https://github.com/zhengye1/Eatr/tree/dev
The Date object is used to get the current date in TypeScript. We can use it to get the current date-time and also change it to different formats. We can create a new Date object and each time we create a Date object, it returns the current date-time. There are different ways to construct a Date object with its constructor.
When we call the getUsers function, Typescript knows that we’re supposed to get back a list of User types, and so we can make use of type annotations: I use VSCode as my editor, but Typescript annotations and autocompletion features are present in most popular text editors.
Typescript helps developers by providing static analysis and autocomplete features for their Javascript code. When calling REST APIs, the response is normally in a serialized format, most commonly JSON.
Typescript helps developers by providing static analysis and autocomplete features for their Javascript code. When calling REST APIs, the response is normally in a serialized format, most commonly JSON. We can then divide the process of integration API calls with Typescript into two parts:
All of the code in getCurrentLocation() will run before the callback given to navigator.geolocation.getCurrentPosition has a chance to run. You can see this by putting another console.log statement inside the callback:
navigator.geolocation.getCurrentPosition((position) => {
console.log("Got position", position.coords);
this.lat = position.coords.latitude;
this.lon = position.coords.longitude;
});
There are a couple of reasons that getCurrentPosition needs to use a callback:
The solution probably involves making a wrapper around getCurrentPosition so that it returns a promise. I don't know how Angular 2 observables work so I won't be able to help much in that part, but you could have getPosition return a promise like so:
getPosition = () => {
return new Promise((resolve, reject) => {
navigator.geolocation.getCurrentPosition((position) => {
resolve(position.coords);
}, (err) => {
reject(err);
});
});
And maybe getCurrentLocation could look like this (just guessing):
async getCurrentLocation(): PromiseLike<any> {
let coords = await this.getPosition(this.lat, this.lon);
this.lat = coords['latitude'];
this.lon = coords['longitude'];
this.params.set('lat', this.lat);
this.params.set('lon', this.lon);
var result = this.http.get(this.url, { search: this.params });
return await result.toPromise();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With