0

I have request to google drive using gapi:

getFolders(folderId: string): Observable<{ id: string, name: string }[]> {
    const promise = gapi.client.drive.files.list({
      fields: 'incompleteSearch,nextPageToken,files(id,name)',
      q: `'${folderId}' in parents`,
    }).then((res) => {
      return JSON.parse(res.result.files);
    });
    return from(promise);
  }

then I try to show this data in component: .ts file ngOnInit:

this.data$ = this.googleDriveService.getFolders(rootFolderId)
        .pipe(
          map((files) => {
            debugger;
            return files.map(file => ({ id: file.id, header: file.name, content: '', imageUrl: this.defaultImageUrl }));
          }),
          takeUntil(this.destroy$),
        );

and html file:

  <mat-grid-tile *ngFor="let elem of (data$ | async)">
    <app-card (input)="returnCartItem(elem)" (click)="goto(elem.header, elem.id)"></app-card>
  </mat-grid-tile>

The problem is that data$ always empty. I added debugger to map to check maybe something wrong with there, but it never goes in map function. From response, I get 2 files, so res.result.files isn't empty;

Dmytro Mysak
  • 1,206
  • 15
  • 28

4 Answers4

1

The problem was in gapi (google API). More info here I created private method inObservable

private inObservable(promise) {
    return from(
      new Promise((resolve, reject) => {
        this.zone.run(() => {
          promise.then(resolve, reject);
        });
      })
    );
  }

And wrap my request into it

const promise = gapi.client.drive.files.list({
      fields: 'incompleteSearch,nextPageToken,files(id,name)',
      q: `'${folderId}' in parents`,
    }).then((res) => {
      return JSON.parse(res.result.files);
    });
return inObservable(promise);
Dmytro Mysak
  • 1,206
  • 15
  • 28
0

You turned getFolders() into an observable, so you have to subscribe to it to start getting data from it.

this.googleDriveService.getFolders(rootFolderId).pipe(...).subscribe();
Paolo
  • 704
  • 9
  • 24
0

I think there is a problem the way async is used, please try this:

<mat-grid-tile *ngFor="let elem of data$ | async">
    <app-card (input)="returnCartItem(elem)" (click)="goto(elem.header, elem.id)"></app-card>
</mat-grid-tile>
Ritesh Waghela
  • 3,474
  • 2
  • 19
  • 25
  • I added `subscribe`, but still get nothing. Then import `private cdr: ChangeDetectorRef` and run in `subscribe`: `this.cdr.detectChanges();` After this angular rerender my component with data. So, it's my temporarily workaround, but to to fix it I have no idea – Dmytro Mysak Apr 22 '19 at 09:49
  • ts file: https://ghostbin.com/paste/j8wu6 html file: https://ghostbin.com/paste/mujx7 – Dmytro Mysak Apr 22 '19 at 09:57
  • I use google api and I change app.module ts file: https://ghostbin.com/paste/usqdj maybe something wrong with him? – Dmytro Mysak Apr 22 '19 at 10:04
  • Do you see any errors in console? How do you know that google session is established. Can you please put a log in initClient method and see if that gets triggered. – Ritesh Waghela Apr 22 '19 at 10:11
  • I use `tap(console.log)` to log response after map and I get an array with 2 items – Dmytro Mysak Apr 22 '19 at 11:16
  • It seems takeUntil is the culprit then. Can you please remove takeUntil and just use take(1) to see if the code inside subscription executes? – Ritesh Waghela Apr 22 '19 at 11:25
  • The problem was in google drive api (gapi). I'll add more description as answer. – Dmytro Mysak May 06 '19 at 09:08
0

I think the issue is that due to your async pipe, the inner elements are tried to be rendered before the async data is loaded. You can do a simple workaround to give your async data a reference variable and render the inner contents once the reference variable is ready as

<ng-container *ngIf="data$ | async as data">
    <mat-grid-tile *ngFor="let elem of data | async">  //note it is not data$
        <app-card (input)="returnCartItem(elem)" (click)="goto(elem.header, elem.id)"> 
        </app-card>
    </mat-grid-tile>
</ng-container
Saksham
  • 9,037
  • 7
  • 45
  • 73