0

This is the almost same question as Typescript getCurrent location and pass to backend to get the result and pass to Material Table data source, but this question I only got the answer for how to get the current location and pass to backend and which it works by libertyernie's answer. Therefore I ask this one...

Here is the issue: I want to use Angular Material 2 table to display the list of restaurant (which is come from my spring-boot backend). And based on the tutorial they gave on github, the data source must be observable, which is make sense, because you can sort column or filter the data something like that. But when I try to integrate with current location, I don't know how to make it work...

The scenario is same as the question I linked, which is try to get user's current location, and once it got the location (for example ,lat=123 and lon=123), I will pass this two parameters into my backend address: http://localhost:8080/api/search/location?lat=123&lon=123, and this will return a list of Restaurant, and I need to somehow change to Observable so that the connect() function in ExampleDataSource works.

The code below is what I already tried, but I am failed, the datasource get nothing back.

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() { }
}

Full code also in Github: https://github.com/zhengye1/Eatr/tree/dev

Nehal
  • 13,130
  • 4
  • 43
  • 59
Vincent Zheng
  • 385
  • 1
  • 4
  • 19
  • Not sure what are you exactly looking to change in `Observable`, but if you are looking for an example on to setup `connect()` to retrieve data from API, you can check this [answer](https://stackoverflow.com/a/45394504/5556177) and the [plunker](https://plnkr.co/edit/ivvQqO5dXB92IXN8zOFv?p=preview) in it. – Nehal Aug 11 '17 at 01:21
  • @Nehal thanks for the comment, let me bring the question easier. I want to get the user's current location when they come to the home page, once my front end get the lat/lon, send it to the backend and return the list of restaurants which is near to the user, so my front end can pick the result back and put into material table and displayed to user. How can I approach this? – Vincent Zheng Aug 11 '17 at 02:33

1 Answers1

0

Finally I can get the information to display to the home page, but weird behavior happens, please see this link : Weird behavior when using Angular Material 2 table (Angular 2/Spring Boot backend)

Vincent Zheng
  • 385
  • 1
  • 4
  • 19