Fernando Ania
Fernando Ania

Reputation: 377

Angular 4 array values are lost

I have a method which assigns an array returned from from a http request to another array. The issue is that it appears that after the method completes, the array with the new values becomes empty.

Method with http request.

loadBookingFullRowDataRequest(rowId: number) {
    this.bookingFullRowData[rowId] = [];
    this.bookingService.getAllBookingData().subscribe(res => {
      this.bookingFullRowData = <Booking[]>res[rowId];
      console.log('all booking data: ', this.bookingFullRowData, 'rowId: ', rowId);
      for (const item of this.bookingFullRowData) {
        const itemId = `${item['title']}-rowid-${item['rowid']}-proj-${item['proj']}`;
        this.bookingsForm.addControl(itemId, new FormControl(
          `${item['content']}`
        ));
      }
    });
  }

data logged to the console

Method which attempts to use the data from the updated array.

launchModal(element) {

    const elementId = (event.target as Element).id;
    const elementIdArray = String(elementId).split('-');
    this.currentRow = parseInt(elementIdArray[2], 10);
    this.loadBookingFullRowDataRequest(this.currentRow);
    console.log('the whole loaded dta:', this.bookingFullRowData, 'row: ', this.currentRow);

    this.modalService.createModal('#bookings-form', null, this.dialogOptions);
  }

The console.log just outputs an empty array.

Upvotes: 1

Views: 449

Answers (3)

Dheeraj Kumar
Dheeraj Kumar

Reputation: 4175

As subscribe funciton is making an asynchronous call, you need to make sure you are using data after call is completed.

Subscribe has 3 parameters/sections.

  1. Data which is returned,
  2. Error if any returned,
  3. Call is completed section

     loadBookingFullRowDataRequest(rowId: number) {
    this.bookingFullRowData[rowId] = [];
    this.bookingService.getAllBookingData().subscribe(res => {
      this.bookingFullRowData = <Booking[]>res[rowId];
      console.log('all booking data: ', this.bookingFullRowData, 'rowId: ', rowId);
      for (const item of this.bookingFullRowData) {
        const itemId = `${item['title']}-rowid-${item['rowid']}-proj-${item['proj']}`;
        this.bookingsForm.addControl(itemId, new FormControl(
          `${item['content']}`
        ));
      }
    }, ()=> {console.log(error)}, // error 
    

    ()=> // call is completed here you can do aftercall tasks { console.log('the whole loaded dta:', this.bookingFullRowData, 'row: ', this.currentRow); this.modalService.createModal('#bookings-form', null, this.dialogOptions)} ); }

Upvotes: 0

DeborahK
DeborahK

Reputation: 60558

The issue is that the getAllBookingData method is asynchronous. That means that it issues a request but does not immediately get a response.

The function we pass into the subscribe method is basically a callback function that is executed when the response is returned.

That means that the code within

this.bookingService.getAllBookingData().subscribe() // <-- HERE

Is executed at some later point in time.

So all of the code after this line:

this.loadBookingFullRowDataRequest(this.currentRow);
// Any code below here!!
console.log('the whole loaded dta:', this.bookingFullRowData, 'row: ', this.currentRow);

this.modalService.createModal('#bookings-form', null, this.dialogOptions);

is executed BEFORE the function passed into the subscribe method.

So to solve your issue, you need to move all code that needs to execute after the data is retrieved within the callback function:

loadBookingFullRowDataRequest(rowId: number) {
    this.bookingFullRowData[rowId] = [];
    this.bookingService.getAllBookingData().subscribe(res => {
      this.bookingFullRowData = <Booking[]>res[rowId];
      console.log('all booking data: ', this.bookingFullRowData, 'rowId: ', rowId);
      for (const item of this.bookingFullRowData) {
        const itemId = `${item['title']}-rowid-${item['rowid']}-proj-${item['proj']}`;
        this.bookingsForm.addControl(itemId, new FormControl(
          `${item['content']}`
        ));
      }
      console.log('the whole loaded dta:', this.bookingFullRowData, 'row: ', this.currentRow);

      this.modalService.createModal('#bookings-form', null, this.dialogOptions);

    });
  }

As a side note, don't use .toPromise Stick with Observables.

Upvotes: 2

basarat
basarat

Reputation: 276105

Your code is not waiting. Notice the comments below:

// Launch async task in terms of subscribe
this.loadBookingFullRowDataRequest(this.currentRow);

// use loaded data *without waiting*
console.log('the whole loaded dta:', this.bookingFullRowData, 'row: ', this.currentRow);

You need to use the data after subscribe is called.

More

Use toPromise and then chain with then. Docs : https://www.learnrxjs.io/operators/utility/topromise.html

Upvotes: 0

Related Questions