Olga
Olga

Reputation: 50

Can't assign a variable immediately from subscribe()

I want to retrieve one row from database and show this information on my page.

The problem is that subscribe is async so it's not executed immediately therefore I can't access the data from the start. This is the error shown when I execute the code:

enter image description here

But this attribute is actually shown on a page since got received eventually. That's how I understand that. I was trying to get rid of this problem for hours and I just can't figure it out. How can I suppress these errors on my browser due to late arrival of data from database?

This is my code:

HTML:

<div class="img-text">
    <div class="img-left">
      <img class="img-responsive" src="assets/person.png">
    </div>
    <div class="img-right">
      <b>Customer name: </b> {{order.customerName}}<br>
    </div>
  </div>

order-details.component.ts

import { Component, OnInit, Input } from '@angular/core';
import { OrdersService } from '../orders.service';
import { Order } from '../order';

@Component({
  selector: 'app-order-details',
  templateUrl: './order-details.component.html',
  styleUrls: ['./order-details.component.scss'],
  providers: [OrdersService]
})
export class OrderDetailsComponent implements OnInit {

  @Input() order: Order;

  constructor(private _ordersService: OrdersService) { }

  ngOnInit() {
    this.getOrder();
    console.log(this.order);
  }

  getOrder(): any {
    this._ordersService.getOrder(1).subscribe(order => this.order = order);
  }

Upvotes: 2

Views: 152

Answers (3)

Corey Ford
Corey Ford

Reputation: 145

Another way would be to initialize an empty order in the constructor:

constructor(private _ordersService: OrdersService) {
    this.order = {};
 }

Upvotes: 0

Explosion Pills
Explosion Pills

Reputation: 191729

You want to make sure the data can be accessed; otherwise you'll try to read from an undefined property. There are a few ways to do this:

<b>Customer name: </b> {{order?.customerName}}<br>

This will still display Customer name: with nothing. Instead you may want to use ngIf with else to show a loading indicator or something like that.

<div class="img-right" *ngIf="order$ | async as order; else loading">
  <b>Customer name: </b> {{order.customerName}}<br>
</div>
<div #loading>Loading...</div>

Note that order probably shouldn't be an input. You will need an order$ property:

order$ = this._ordersService.getOrder(1);

The | async takes care of the subscribe and unsubscribe for you.

Upvotes: 4

Mixalloff
Mixalloff

Reputation: 837

You can use ? operator: order?.customerName

Upvotes: 2

Related Questions