Angular 2 Facebook Login - javascript

I am developing an website that needs to be logged in with Facebook account. I am using Angular 2 and, of course, TypeScript. It works But not exactly what I wanted. I can't take back the user's information.
Let's go to the code:
import {Component} from 'angular2/core';
import {Main} from './pages/main/main';
declare const FB: any;
#Component({
selector: 'my-app',
templateUrl: 'app/app.html',
directives: [Main]
})
export class AppComponent implements OnInit {
token: any;
loged: boolean = false;
user = { name: 'Hello' };
constructor() { }
statusChangeCallback(response: any) {
if (response.status === 'connected') {
console.log('connected');
} else {
this.login();
}
}
login() {
FB.login(function(result) {
this.loged = true;
this.token = result;
}, { scope: 'user_friends' });
}
me() {
FB.api('/me?fields=id,name,first_name,gender,picture.width(150).height(150),age_range,friends',
function(result) {
if (result && !result.error) {
this.user = result;
console.log(this.user);
} else {
console.log(result.error);
}
});
}
ngOnInit() {
FB.getLoginStatus(response => {
this.statusChangeCallback(response);
});
}
}
Basically, When the page loads I check if the user is logged in to Facebook, if not, I call the login method. The me method is used to fetch the users information, like its name, first name etc. When I logged in condition browser console print the following line:
Object {id: "666", name: "Paulo Henrique Tokarski Glinski", first_name: "Paulo", gender: "male", picture: Object…}
Everything ok! But I want to get that Object and put into a User object! Something like that:
me method:
this.user = result;
console.log(this.user);
But the user just exists inside the method. If I print it outside, its returns nothing.
I just want to print the users name etc. at the website page. I did almost the same thing with Angular JS and worked well.
Please! Help me!

you can use fat arrow functions to use the same context ...
login() {
FB.login((result: any) => {
this.loged = true;
this.token = result;
}, { scope: 'user_friends' });
}

For the facebook javascript SDK, You just add the following line in your index.html
<script src="//connect.facebook.net/en_US/sdk.js"></script>
and in ngOnInit() :
`FB.init({
appId : 'your-app-id',
cookie : false,
xfbml : true, // parse social plugins on this page
version : 'v2.5' // use graph api version 2.5
});`

Angular 2 Service level implementation
import {Injectable} from '#angular/core';
import { Location } from '#angular/common';
import { Http, Response, Headers, RequestOptions,URLSearchParams } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import { ConfigService } from "app/core/services/config.service";
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
#Injectable()
export class AuthService {
constructor(private http: Http,
private configProvider:ConfigService) {
}
authenticateFacebook(){
window.location.href = 'https://www.facebook.com/v2.9/dialog/oauth?client_id='+
this.configProvider.config.facebook.clientId +
'&redirect_uri='+ this.configProvider.config.facebook.redirectURI + '&scope=public_profile';
}
getAccessToken(authenticationCode: string){
var authProviderUrl = 'https://graph.facebook.com/v2.9/oauth/access_token';
var authParameters = {
client_id: this.configProvider.config.facebook.clientId,
redirect_uri: this.configProvider.config.facebook.redirectURI,
client_secret: this.configProvider.config.facebook.clientSecret,
code: authenticationCode
};
var params = [];
for (var k in authParameters) {
params.push(k + '=' + authParameters[k]);
}
var authOpenURI = authProviderUrl + '?' + params.join('&');
return this.http.get(authOpenURI)
.map(res => res.json())
.catch(err => Observable.throw(err));
}
getUserFacebookProfile(accessToken:string):Observable<any>{
var fields = ['id', 'email', 'first_name', 'last_name', 'link', 'name','picture.type(small)'];
var graphApiUrl = 'https://graph.facebook.com/v2.5/me?fields=' + fields.join(',');
return this.http.get(graphApiUrl+'&access_token='+accessToken+'')
.map(res => res.json())
.catch(err => Observable.throw(err));
}
Caller level function, this code will be in the component of your redirect URI
//Facebook authentication check
if (window.location.href.indexOf("code") > -1){
var code = window.location.href.substring(window.location.href.indexOf("?") + 1).split('&')[0].split('=')[1];
this.getFaceBookProfile(code);
}
//Get profile from facebook
getFaceBookProfile(code:string){
this.authService.getAccessToken(code).subscribe(oathAccessData => {
this.authService.getUserFacebookProfile(oathAccessData.access_token).subscribe(profile => {
this.userProfile = new UserProfile(profile.name,profile.email, profile.picture.data.url,"facebook",
profile.id);},err => { console.log(err); });},err => { console.log(err);});
this.router.navigate(['/dashboard']);
}

this has a bunch of magic involved. Does it help if you capture the class's this in a variable and use that in the callbacks (so as to avoid caring what their this is)?
e.g.
login() {
var self = this;
FB.login(function(result) {
self.loged = true;
self.token = result;
}, { scope: 'user_friends' });
}

Related

How to hold alert box on the page in case of reloading or changing route?

I need to maintain an alert box on the Registration page indicating the user has registered successfully. However, by redirecting to the Login form this box disappears, because the page refreshes.
I utilize the Alert component to manage this scenario. All of the features work flawlessly but this problem really makes me confused. I shared my code and hope you assist me in getting to the root of this predicament.
alert.component.ts
import { Component, OnInit, OnDestroy, Input } from '#angular/core';
import { Router, NavigationStart } from '#angular/router';
import { Subscription } from 'rxjs';
import { Alert, AlertType } from 'src/app/_models/alert';
import { AlertService } from 'src/app/_services/alert.service';
#Component({ selector: 'alert',
templateUrl: 'alert.component.html',
styleUrls: ['./alert.component.scss'] })
export class AlertComponent implements OnInit, OnDestroy {
#Input() id = 'default-alert';
#Input() fade = true;
alerts: Alert[] = [];
alertSubscription: Subscription;
routeSubscription: Subscription;
constructor(private router: Router, private alertService: AlertService) { }
ngOnInit() {
// subscribe to new alert notifications
this.alertSubscription = this.alertService.onAlert(this.id)
.subscribe(alert => {
// clear alerts when an empty alert is received
if (!alert.message) {
// filter out alerts without 'keepAfterRouteChange' flag
this.alerts = this.alerts.filter(x => x.keepAfterRouteChange);
// remove 'keepAfterRouteChange' flag on the rest
this.alerts.forEach(x => delete x.keepAfterRouteChange);
return;
}
// add alert to array
this.alerts.push(alert);
setTimeout(() => this.removeAlert(alert), 5000);
});
// clear alerts on location change
this.routeSubscription = this.router.events.subscribe(event => {
if (event instanceof NavigationStart) {
this.alertService.clear(this.id);
}
});
}
ngOnDestroy() {
// unsubscribe to avoid memory leaks
this.alertSubscription.unsubscribe();
this.routeSubscription.unsubscribe();
}
removeAlert(alert: Alert) {
// check if already removed to prevent error on auto close
if (!this.alerts.includes(alert)) return;
if (this.fade) {
// fade out alert
this.alerts.find(x => x === alert).fade = true;
// remove alert after faded out
setTimeout(() => {
this.alerts = this.alerts.filter(x => x !== alert);
}, 250);
} else {
// remove alert
this.alerts = this.alerts.filter(x => x !== alert);
}
}
cssClass(alert: Alert) {
if (!alert) return;
const classes = ['toast'];
const alertTypeClass = {
[AlertType.Success]: 'toast-success',
[AlertType.Error]: 'toast-error',
[AlertType.Info]: 'toast-info',
[AlertType.Warning]: 'toast-warning'
}
classes.push(alertTypeClass[alert.type]);
if (alert.fade) {
classes.push('fade');
}
return classes.join(' ');
}
}
alert.service.ts
import { Injectable } from '#angular/core';
import { Observable, Subject } from 'rxjs';
import { filter } from 'rxjs/operators';
import { Alert, AlertType } from '../_models/alert';
#Injectable({ providedIn: 'root' })
export class AlertService {
private subject = new Subject<Alert>();
private defaultId = 'default-alert';
// enable subscribing to alerts observable
onAlert(id = this.defaultId): Observable<Alert> {
return this.subject.asObservable().pipe(filter(x => x && x.id === id));
}
// convenience methods
success(message: string, options?: any) {
this.alert(new Alert({ ...options, type: AlertType.Success, message }));
}
error(message: string, options?: any) {
this.alert(new Alert({ ...options, type: AlertType.Error, message }));
}
info(message: string, options?: any) {
this.alert(new Alert({ ...options, type: AlertType.Info, message }));
}
warn(message: string, options?: any) {
this.alert(new Alert({ ...options, type: AlertType.Warning, message }));
}
// main alert method
alert(alert: Alert) {
alert.id = alert.id || this.defaultId;
this.subject.next(alert);
}
// clear alerts
clear(id = this.defaultId) {
this.subject.next(new Alert({ id }));
}
}
This is a piece of code in which an alert message is called (It should be noted that the keepAfterRouteChange is set to True):
onSubmit() {
this.submitted = true;
// reset alerts on submit
this.alertService.clear();
// stop here if form is invalid
if (this.form.invalid) {
return;
}
this.loading = true;
this.accountService
.register(this.form.value)
.pipe(first())
.subscribe((data) => {
this.loading = false;
this.submitted = false;
if (data.hasError) {
this.alertService.error(data.errorMessage);
} else {
this.alertService.success('Registration successfully completed.', {
keepAfterRouteChange: true,
});
localStorage.setItem('regCount',JSON.parse(localStorage.getItem('regCount')) + 1);
this.router.navigate(['/login']).then(() => {
window.location.reload();
});
}
},
() => {
this.loading = false;
this.submitted = false;
this.alertService.error('Something went wrong.');
});
}
Your problem probably comes from window.location.reload(); when window is reloaded all components and services are flushed. Find other ways to clear services if that's the point this line. Or find other way to store info that alert should be showing (e.g storing the need to show an alert with info and duration in SessionStorage or LocalStorage) - which doesn't seem like a good idea though. Normally we want to avoid reloading windows - for the same reason, losing all data and forcing the client to reload all resources.

Angular PayPal Processing, Childcomponent and Lifecycle

I am currently working on the PayPal integration in my own shop (Angular Frontend, dotnet core WebApi backend) and apparently I have a problem with the life cycle between the main component (CheckoutProcessComponent) and the child component (PaymentPayPalComponent) and with the use of the necessary PayPal javascript.
Basically the complete PayPal workflow works as long as I use static variables. And this is exactly where my problem starts.
CheckoutProcessComponent.ts
import { Component, OnInit } from '#angular/core';
import { CartService } from 'src/app/_services/shop/cart.service';
import { ISubscriptionCollection } from 'src/app/_models/misc/ISubscriptionCollection';
import { serialUnsubscriber } from 'src/app/shared/utility.module';
import { CheckoutService } from 'src/app/_services/checkout/checkout.service';
import { ICheckoutOrderData } from 'src/app/_models/shop/ICheckoutOrderData';
import { IOrderProcessSummary } from 'src/app/_models/shop/IOrderProcessSummary';
#Component({
selector: 'app-checkout-process',
templateUrl: './checkout-process.component.html',
styleUrls: ['./checkout-process.component.css']
})
export class CheckoutProcessComponent implements OnInit {
subscriptions: ISubscriptionCollection = {};
checkoutOrderData = {} as ICheckoutOrderData;
orderSummaryFromServer: IOrderProcessSummary;
orderCreated: boolean = false;
constructor(public checkoutService: CheckoutService, public cartService: CartService) { }
ngOnInit() {
this.checkoutOrderData.Order = this.checkoutService.orderData;
this.checkoutOrderData.Cart = this.cartService.shoppingCart;
// Create Order
this.subscriptions['createOrder'] = this.checkoutService.createOrder(this.checkoutOrderData)
.subscribe((res: IOrderProcessSummary) => {
this.checkoutService.checkoutSummary = res;
this.orderSummaryFromServer = res;
console.log('Order created: ' + res);
}, error => {
console.log('Error');
});
}
ngOnDestroy(): void {
serialUnsubscriber(...Object.values(this.subscriptions));
}
nextStep(step: number) {
this.checkoutService.updateCheckoutStep(step);
}
...
}
CheckoutProcessComponent.html
<app-payment-paypal [orderSummary]="orderSummaryFromServer" *ngIf="checkoutService.orderData.paymentMethod === 'PM_PAYPAL'"></app-payment-paypal>
<app-payment-stripe *ngIf="checkoutService.orderData.paymentMethod === 'PM_STRIPE'"></app-payment-stripe>
<app-payment-moneytransfer *ngIf="checkoutService.orderData.paymentMethod === 'PM_TRANSFER'"></app-payment-moneytransfer>
PaymentPayPalComponent.ts
import { Component, OnInit, AfterViewChecked, Input } from '#angular/core';
import { environment } from 'src/environments/environment';
import { IOrderProcessSummary } from 'src/app/_models/shop/IOrderProcessSummary';
import { CheckoutService } from 'src/app/_services/checkout/checkout.service';
declare let paypal: any;
#Component({
selector: 'app-payment-paypal',
templateUrl: './payment-paypal.component.html',
styleUrls: ['./payment-paypal.component.css']
})
export class PaymentPaypalComponent implements OnInit, AfterViewChecked {
#Input() orderSummary: IOrderProcessSummary;
paypalClientId = environment.paymentPayPal.clientId;
addScript: boolean = false;
scriptTagElement: HTMLScriptElement;
constructor(private checkoutService: CheckoutService) { }
ngOnInit() {
}
ngOnDestroy(): void {
if (this.scriptTagElement) {
document.body.removeChild(this.scriptTagElement);
}
}
ngAfterViewChecked(): void {
if (!this.addScript) {
this.addPayPalScript().then(() => {
paypal.Buttons({
createOrder: function() {
return fetch('https://localhost:5021/api/payments/paypal-create-order', {
method: 'post',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
orderId: 1234
})
}).then(function(res) {
return res.json();
}).then(function(data) {
return data.id; // Use the same key name for order ID on the client and server
});
},
onApprove: function(data, actions) {
console.log('onApprove - transaction was approved, but not authorized', data, actions);
actions.order.get().then(details => {
console.log('onApprove - you can get full order details inside onApprove: ', details);
});
return fetch('https://localhost:5021/api/payments/paypal-capture-order', {
method: 'post',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
token: data.orderID,
payerID: data.payerID,
})
});
},
onClientAuthorization: (data) => {
console.log('onClientAuthorization - you should probably inform your server about completed transaction at this point', data);
// this.showSuccess = true;
},
onCancel: (data, actions) => {
console.log('OnCancel', data, actions);
// this.showCancel = true;
},
onError: err => {
console.log('OnError', err);
// this.showError = true;
}
}).render('#paypal-button-container');
})
}
}
addPayPalScript() {
return new Promise((resolve, reject) => {
this.scriptTagElement = document.createElement('script');
this.scriptTagElement.src = 'https://www.paypal.com/sdk/js?currency=EUR&client-id=' + this.paypalClientId;
this.scriptTagElement.onload = resolve;
document.body.appendChild(this.scriptTagElement);
this.addScript = true;
})
}
}
PaymentPayPalComponent.html
<div class="text-center" id="paypal-button-container"></div>
The processing flow is as follows:
CheckoutProcessComponent > creates the order on the server with the cart data and stores the order in the database (general function, non PayPal related)
The result from 1. is of IOrderProcessSummary which holds the order Id and the total of the order
Depending on the selected payment method, the corresponding payment-Child Component will be displayed. In this case the PaymentPayPalComponent.
Then I use the PayPal-feature "CreatePayPalOrderOnServer" which uses the PayPal Api in my backend to create an order on the PayPal server. But for that I need the specific orderId because I need to fill the PayPal-Order data with the specific order data from my system (in the example I have a fixed 1234 order Id).
For step 4. I tried it with Input()-parameter and with injecting the CheckoutService to the PaymentPayPalComponent but I am not able to work with any kind of dynamic variables within the PayPal-Button-Function (JavaScript). In the example I need to change the "orderId: 1234" with a value from the Input() orderSummary or the same value from the CheckoutService, but both of them stay undefined.
The PayPal-Javascript is loaded correctly and the PayPal-Buttons show up and work as intended technically.
How do I bring my dynamic data into the PaymentPayPalComponent and into the PayPal.Buttons-Function?
Thanks for your tips!

Angular component property inexplicably remains "undefined" after being set in subscribe()

Let me just preface this by saying yes, i'm using arrow functions to retain the scope of "this" (as far as I can tell anyway).
I have two properties on my component:
IsAdmin (boolean)
currentRole (string)
I make an api call to fetch user roles from my backend via Angular's HttpClient, and I have a callback subscribe-method which updates above mentioned properties with the result.
However, while I can assign the role value to currentRole, the other property IsAdmin remains undefined even as I assign it, and I get no error in my f12 debugger or visual studio code via the chrome plugin.
import { Component, OnInit } from "#angular/core";
import { AuthorizeService, IUser } from "../authorize.service";
import { Observable } from "rxjs";
import { map, tap } from "rxjs/operators";
import { HttpClient } from "#angular/common/http";
#Component({
selector: "app-login-menu",
templateUrl: "./login-menu.component.html",
styleUrls: ["./login-menu.component.scss"]
})
export class LoginMenuComponent implements OnInit {
isAuthenticated: Observable<boolean>;
public userName: Observable<string>;
IsAdmin : boolean;
currentRole : string;
constructor(private authorizeService: AuthorizeService, private http : HttpClient) {
}
ngOnInit() {
this.isAuthenticated = this.authorizeService.isAuthenticated();
this.userName = this.authorizeService.getUser().pipe(map(u => u && u.name));
const endpoint = '.../api/User/User/GetRoles';
this.authorizeService.getUser()
.subscribe(data => {
this.userNameSignedIn = data.name;
});
this.http.get<string[]>(endpoint).
subscribe(result => {
this.currentRole = result[0];
console.log("this.currentRole ", this.currentRole); //prints "admin"
this.IsAdmin == result.includes("admin");
console.log("this.IsAdmin", this.IsAdmin); //prints "undefined"
}, error => console.error(error));
}
}
Console output is as following:
logon-menu.component.ts:37 this.currentRole admin
logon-menu.component.ts:39 this.IsAdmin undefined
What on earth is going on here? What am I doing wrong?
the problem in your subscribe is that you are using ==(comparison) instead of = (assignation)
subscribe(result => {
this.currentRole = result[0];
console.log("this.currentRole ", this.currentRole); //prints "admin"
this.IsAdmin == result.includes("admin"); //<-- here is an error
console.log("this.IsAdmin", this.IsAdmin); //prints "undefined"
},
your code should be:
subscribe(result => {
this.currentRole = result[0];
this.IsAdmin = result.includes("admin");
},

How can retrieve a data by parameter in Ionic 3 with Firebase

I have a real-time database on Firebase, and I want to retrieve records from this database using parameters.
For example, in the hierarchy you see, I want to get the data using the uID value. How can I do that?
UPDATE
https://javebratt.com/firebase-objects-ionic-2-app/
I have tried the heading "Read Firebase Data" in the article on the link I gave, but I do not know how to update the code if it is written for Ionic 2.
Here is the code I wrote,
import { Component } from '#angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { Post } from '../../models/models/post';
import { AngularFireDatabase } from 'angularfire2/database';
import { Storage } from '#ionic/storage';
#IonicPage()
#Component({
selector: 'page-profile',
templateUrl: 'profile.html',
})
export class ProfilePage {
public posts: Post[];
public uID: string;
constructor(public navCtrl: NavController,
public navParams: NavParams,
private db: AngularFireDatabase,
private storage: Storage) {
this.storage.get('uID').then((val) => {
console.log('uID: ' + val);
this.uID = val;
console.log('this.uID: ' + this.uID);
this.db.list<Post>('/Post/',
ref => ref.orderByChild('uID').equalTo(this.uID)).valueChanges().subscribe(t => {
this.posts = t;
})
});
}
ionViewDidLoad() {
console.log('ionViewDidLoad ProfilePage');
}
}
According to the article I had to do create a variable which is type of "Reference", but with AngularFireDatabase it is not possible to make such a definition.
How do I update this definition in Ionic 3?
UPDATE
I added some codes;
db.database.ref('/User/').on('value', res => {
console.log("Try Val: " + res.val)
console.log("Try Key: " + res.key)
console.log("Try Child: " + res.child)
});
And outputs;
Try Val: function () {
util_1.validateArgCount('DataSnapshot.val', 0, 0, arguments.length);
return this.node_.val();
}
Try Key: User
Try Child: function (childPathString) {
util_1.validateArgCount('DataSnapshot.child', 0, 1, arguments.length);
// Ensure the childPath is a string (can be a number)
childPathString = String(childPathString);
validation_1.validatePathString('DataSnapshot.child', 1, childPathString, false);
var childPath = new Path_1.Path(childPathString);
var childRef = this.ref_.child(childPath);
return new DataSnapshot(this.node_.getChild(childPath), childRef, PriorityIndex_1.PRIORITY_INDEX);
}
UPDATE
I could get data, but it's not clear answer.
Firebase records all data with a key value. I also added this key value after the "/ Post /" value as the data path. For example "/ Post / -1ersksnu0nsw1 /".
Here is the code;
db.database.ref('/User/-L88gtymS5pS3KWtZrmI').on('value', res => {
console.log(res.val().email)
});
And I could get true value, but I still do not know how to do this according to the columns of their records.
EUREKA!
db.database.ref('/User/').orderByChild('uID').equalTo(this.uID).once('value', (snapshot) => {
console.log(snapshot.val().email)
})
This code will do that.
You can checkout this tutorial. It create a chat app but it may help you on what you want to to.
firebase.database().ref('/Post/').on('value', resp => {
console.log(resp)
});

Weird behavior when using Angular Material 2 table (Angular 2/Spring Boot backend)

Continue to the Using angular material 2 table to display the result from backend based on user's current location
My purpose for this code is when user enter the site, it will try to ask user the current location. Once my front end get current lat/lon, it will pass to backend to get the nearest restaurant based on user's location, and using angular material table to display it. But when I testing on Chrome, I got weird behavior, the home page will not display the result immediately on the first time, try refresh, doesn't work, the only way make it works is switch another tab, and back to this one, it will display the result in angular material table.
Here is the code for home.component.ts
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 'rxjs/add/observable/frompromise';
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'];
dataSource: ExampleDataSource | null;
constructor(http: Http) {
//this.exampleDatabase = new ExampleHttpDatabase(http, this.location);
this.dataSource = new ExampleDataSource(http);
}
ngOnInit() {
this.dataSource.connect();
}
}
export class ExampleDataSource extends DataSource<Restaurant> {
private url = 'api/search/location';
private params = new URLSearchParams();
private lat;
private lon;
constructor(private http: Http) {
super();
}
/** Connect function called by the table to retrieve one stream containing the data to render. */
connect(): Observable<Restaurant[]> {
// var location;
// if (navigator.geolocation){
// var options = {timeout: 60000};
// location = navigator.geolocation.getCurrentPosition((position)=>{
// return position;
// },(err) =>{
// console.log("Error")
// }, options);
// }
// console.log("Locations: " + location);
var result = this.getCurrentLocation().then((res) =>
{
return res;
});
return Observable.fromPromise(result);
}
disconnect() { }
getPosition = () => {
var latitude, longitude;
return new Promise((resolve, reject) => {
navigator.geolocation.getCurrentPosition((position) => {
resolve(position.coords);
}, (err) => {
reject(err);
});
})
}
async getCurrentLocation(): Promise<Restaurant[]> {
let coords = await this.getPosition();
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 }).map(this.extractData);
return await result.toPromise();
}
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.cityName
}
});
}
}
I don't know what I did wrong.. can someone help me? For the full code, please see https://github.com/zhengye1/Eatr/tree/dev
Finally solved....
All I need to do just change ngOnInit on HomeComponent class to following
async ngOnInit() {
await this.dataSource.connect();
}
and it works.. don't know why...

Categories