0

I am trying to make this to where when a user "clicks" on the card for each restaurant it will open a page (selected-card.page) where additional details (menu, price, etc) could be found. I am not quite sure how to get this done and am currently trying to use a function in a service to call to the API to display that restaurant.

I realize I am likely far from getting this done and if you have a guide or tutorial that would help feel free to send that to me. Thanks for the help!

dining.page.html (page with cards that you would click to access more details)

  <ion-card (click)="onSelected(card)" class="welcome-card" *ngFor="let item of restaurantsService.restaurants">
    <img class='image' src='{{ item.restaurant.featured_image }}' alt='' />
    <ion-card-header>
      <ion-card-title class='text'>{{ item.restaurant.name }}</ion-card-title>
      <ion-card-subtitle class='text'>{{ item.restaurant.phone_numbers }}</ion-card-subtitle>
      <ion-card-subtitle class='text'>{{ item.restaurant.location.address }}</ion-card-subtitle>
    </ion-card-header>
  </ion-card>
</ion-content>

dining.page.ts

import { ModalController } from '@ionic/angular';
import { RestaurantsService } from '../services/restaurants.service';
import { Observable } from 'rxjs';
import { SelectedCardPage } from '../selected-card/selected-card.page';

@Component({
  selector: 'app-dining',
  templateUrl: './dining.page.html',
  styleUrls: ['./dining.page.scss'],
})
export class DiningPage implements OnInit {

  constructor( private restaurantsService: RestaurantsService,
               public modalCtrl: ModalController ) { };

  ngOnInit() {}

  async onSelected(card) {
      const modal = await this.modalCtrl.create({
        component: SelectedCardPage,
        componentProps: { value: card }
      });
      return await modal.present();
  }

  ionViewWillEnter() {
    this.restaurantsService.fetchRestaurants().subscribe();
  }


}

selected-card.page.html

<ion-content>
  <ion-card (click)="dismiss()" class="welcome-card" *ngFor="let item of restaurantsService.restaurants">
    <img class='image' src='{{ item.restaurant.featured_image }}' alt='' />
    <ion-card-header>
      <ion-card-title class='text'>{{ item.restaurant.name }}</ion-card-title>
      <ion-card-subtitle class='text'>{{ item.restaurant.phone_numbers }}</ion-card-subtitle>
      <ion-card-subtitle class='text'>{{ item.restaurant.location.address }}</ion-card-subtitle>
    </ion-card-header>
  </ion-card>
</ion-content>

selected-card.page.ts

import { ModalController, NavParams } from '@ionic/angular';
import { RestaurantsService } from '../services/restaurants.service';

@Component({
  selector: 'app-selected-card',
  templateUrl: './selected-card.page.html',
  styleUrls: ['./selected-card.page.scss'],
})
export class SelectedCardPage implements OnInit {
  value: string;
  constructor(private restaurantsService: RestaurantsService,
              private modalCtrl: ModalController,
              private navParams: NavParams) { }

  ngOnInit() {
  }

  ionViewWillEnter() {
    this.restaurantsService.fetchRestaurantDetails().subscribe();
  }

  ionViewDidLoad() {
    this.value = this.navParams.get('value');
  }

  dismiss() {
    this.modalCtrl.dismiss();
  }

}

restaurant.service.ts

import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class RestaurantsService {
  public restaurants = [];
  public providers = [];

  constructor( public http: HttpClient ) { }

//initial fetchRestaurants that loads on opening dining page
  fetchRestaurants() {
    console.log('fetching restaurants');
    let headers = {'content-type': 'application/json',
                    'accept': 'application/json',
                    'user-key': '7ae71880177b226bed309d0533717b4b'};
    let url = 'https://developers.zomato.com/api/v2.1/search?entity_id=757&entity_type=city&count=20'
    return this.http.get(url, {headers: headers}).pipe(tap(response => {
      console.log(response);
      this.restaurants = response['restaurants'];
      console.log(this.restaurants);
    }));
  }

  // used to obtain information/details on a restaurant when selected
  fetchRestaurantDetails() {
    console.log('getting restaurant details');
    let headers = {'content-type': 'application/json',
                    'accept': 'application/json',
                    'user-key': '7ae71880177b226bed309d0533717b4b'};
    let url = 'https://developers.zomato.com/api/v2.1/reviews?res_id=17266091'
    return this.http.get(url, {headers: headers}).pipe(tap(response => {
      console.log(response);
      this.restaurants = response['restaurants'];
      console.log(this.restaurants);
    }));
  }
}

2 Answers2

0

You are not sending data to your Restaurant details page (SelectedCardPage). Your click function passes 'card' but a variable or object with that name doesn't exist. Use 'item' because your For loop is referring to each restaurant by name 'item' Your Code:

<ion-card (click)="onSelected(card)" class="welcome-card" *ngFor="let item of restaurantsService.restaurants">

Changes:

<ion-card (click)="onSelected(item)" class="welcome-card" *ngFor="let item of restaurantsService.restaurants">

Now, in your SelectedCardPage template, you can display the data that each restaurant item is holding.

<ion-content>
  <ion-card (click)="dismiss()" class="welcome-card">
    <img class='image' src='{{ item.restaurant.featured_image }}' alt='' />
    <ion-card-header>
      <ion-card-title class='text'>{{ item.restaurant.name }}</ion-card-title>
      <ion-card-subtitle class='text'>{{ item.restaurant.phone_numbers }}</ion-card-subtitle>
      <ion-card-subtitle class='text'>{{ item.restaurant.location.address }}</ion-card-subtitle>
    </ion-card-header>
  </ion-card>
</ion-content>
Pankaj Sati
  • 2,441
  • 1
  • 14
  • 21
  • That fixed part of the problem. Now I am trying to use the fetchRestaurantDetails function on restaurants.service.ts and it keeps just bringing up a blank screen and printing "undefined" to the console... not an undefined error necessarily but just the word "undefined" – doublepancake84 Nov 22 '19 at 05:49
  • Your fetchRestaurantDetails() function doesn't accept any restaurant ID or something to uniquely fetch a restaurant. You need to send restaurant ID to that function which you are getting in onViewDidLoad(). Also, please post your full console log. – Pankaj Sati Nov 22 '19 at 06:17
0

Since you are making the whole card clickable and you are running a loop over it to bind details.

<ion-card (click)="onSelected(card)" class="welcome-card" *ngFor="let item of 
restaurantsService.restaurants">
<img class='image' src='{{ item.restaurant.featured_image }}' alt='' />
<ion-card-header>
<ion-card-title class='text'>{{ item.restaurant.name }}</ion-card-title>
<ion-card-subtitle class='text'>{{ item.restaurant.phone_numbers }}</ion-card- 
subtitle>
<ion-card-subtitle class='text'>{{ item.restaurant.location.address }}</ion-card- 
subtitle>
</ion-card-header>
</ion-card>
</ion-content>

Wrong:

 <ion-card (click)="onSelected(card)" class="welcome-card" *ngFor="let item of 
restaurantsService.restaurants">

You need to pass 'item' in the click function. Right:

 <ion-card (click)="onSelected(item)" class="welcome-card" *ngFor="let item of 
restaurantsService.restaurants">
Mridul
  • 1,320
  • 1
  • 5
  • 19