1

Im trying to fetch one object (Type 'Coupon') from DB , and show it when I click on object from list in HTML.

The problem is, When the page loads on, the object details appear the way I wanted it to,But! the consםle also shows "ERROR TypeError: Cannot read property 'imageURL' of undefined".

My code:

step - 1: storage.service.ts (HTTP Request):

@Injectable()
export class StorageService {
token: string

constructor(private http: HttpClient) { }

fetchCouponById(couponId: string): Observable<Coupon> {
const params = new HttpParams()
  .set('token', this.token)
  .set('couponId', couponId)
return this.http.get<Coupon>('http://localhost:8080/api/company/get_coupon', { params })
}

step - 2: company.service.ts :

@Injectable()
export class CompanyService {

@Output() selectedCoupon = new EventEmitter<Coupon>()
coupon: Coupon

fetchCouponById(id: string) {
this.storagService.fetchCouponById(id)
  .subscribe(coupon => {
    this.coupon = coupon
    this.onSelectCoupon()
  })
}

onSelectCoupon() {
this.selectedCoupon.emit(this.getCoupon())
}

getCoupon() {
return this.coupon
}

step - 3: company-coupons-page.ts:

export class CompanyCouponsPageComponent implements OnInit {

coupon: Coupon
selectedCoupon: string

constructor(
    private companyService: CompanyService,
private route: ActivatedRoute) { }

ngOnInit(): void {
this.route.params.subscribe((params: Params) => { this.selectedCoupon = params['id'] })
this.companyService.fetchCouponById(this.selectedCoupon)
this.companyService.selectedCoupon.subscribe(
  (coupon: Coupon) => { this.coupon = coupon})
}

company-coupons-page.HTML:

<div class="container">
      <div class="row">
                <div class="col-6"
                     style="height: 70%; 
                          width: 40%;">
                          <img src={{coupon.imageURL}}
                               alt="..."
                               style="width: 100%;height: 100%; ">
                </div>
                <div class="col-6">
                          <h1>{{coupon.title}}</h1>
                          <h3>{{coupon.amount}}</h3>
                          <h3>{{coupon.category}}</h3>
                </div>
    </div>
Avinadav
  • 45
  • 6

2 Answers2

1

coupon is initially undefined that's why you are getting this typeerror. You can use *ngIf="coupon?.imageUrl" (notice the use of optional chaining, you can also just check for coupon) to render the element only when the coupon exists.

You can also use it for the below elements

<div class="container">
      <div class="row">
                <div class="col-6"
                     style="height: 70%; 
                          width: 40%;">
                          <img *ngIf="coupon?.imageUrl" src={{coupon.imageURL}}
                               alt="..."
                               style="width: 100%;height: 100%; ">
                </div>
                <div class="col-6">
                          <h1 *ngIf="coupon?.title">{{coupon.title}}</h1>
                          <h3 *ngIf="coupon?.amount">{{coupon.amount}}</h3>
                          <h3 *ngIf="coupon?.category">{{coupon.category}}</h3>
                </div>
    </div>
Petros
  • 550
  • 3
  • 13
0

It's always better to be on the safe side by checking whether the object is present or not before you set a dynamic value to it.

You can do this from the HTML or from component.ts file.

*************************
******* FROM HTML *******
*************************
<div class="row" *ngIf="coupon">
   <div *ngIf="coupon.imageUrl" class="col-6" style="height: 70%; width: 40%;">
       <img src={{coupon.imageURL}} alt="..." style="width: 100%;height: 100%; ">
   </div>
    <div class="col-6" *ngIf="coupon.title && coupon.amount && coupon.category">
       <h1>{{coupon.title}}</h1>
       <h3>{{coupon.amount}}</h3>
       <h3>{{coupon.category}}</h3>
    </div>
</div>


***************************************
******* FROM service.ts file ********
***************************************
@Injectable()
export class CompanyService {

@Output() selectedCoupon = new EventEmitter<Coupon>()
coupon: Coupon

fetchCouponById(id: string) {
this.storagService.fetchCouponById(id)
  .subscribe(coupon => {
    if (coupon) {
       this.coupon = coupon
       this.onSelectCoupon()
    }
  })
}

onSelectCoupon() {
  this.selectedCoupon.emit(this.getCoupon())
}

getCoupon() {
  return this.coupon
}

This way you will be very sure that you have the object before you assign it anywhere. 
Srikar Phani Kumar M
  • 1,069
  • 1
  • 3
  • 8