Nodonisko / ionic-cache

Angular cache service with IndexedDB, SQLite and WebSQL support
MIT License
262 stars 74 forks source link

ngFor not working after adding cache #53

Closed lpeppe closed 6 years ago

lpeppe commented 7 years ago

Hi everyone, I've just added this module to my application and it works just fine for all the pages, except from the following one:

<ion-header>

  <ion-navbar>
    <ion-title>{{navParams.get('name')}}</ion-title>
  </ion-navbar>

</ion-header>

<ion-content padding>
  <ion-segment [(ngModel)]="view">
    <ion-segment-button value="info">
      Info
    </ion-segment-button>
    <ion-segment-button value="recensioni">
      Recensioni
    </ion-segment-button>
  </ion-segment>

  <div [ngSwitch]="view">
    <div id="info">
      <div *ngSwitchCase="'info'">
        <div class="flexBox">
          <div *ngIf="details != undefined" [style.background]="(details.open_now) ? 'green' : 'red'"></div>
          <span *ngIf="details != undefined && details.open_now">Aperto</span>
          <span *ngIf="details != undefined && !details.open_now">Chiuso</span>
          <ion-icon name="call" (click)="call()"></ion-icon>
          <ion-icon name="navigate" (click)="navigateTo()"></ion-icon>
        </div>
      </div>
      <div #map2 [style.height]="(view == 'info') ? '35vh' : '0px'"></div>
      <div *ngSwitchCase="'info'" id="slides">
        <ion-slides *ngIf="details != undefined">
          <ion-slide *ngFor="let img of details.photos" (click)="openImg($event)">
            <img [src]="'https://maps.googleapis.com/maps/api/place/photo?key=AIzaSyD_9bj_Ao6nklX7PWrM_1E-iDH4EPVWV6A&maxwidth=1600&photoreference=' + img.photo_reference" />
          </ion-slide>
        </ion-slides>
      </div>
    </div>

    <div id="rec">
      <div *ngSwitchCase="'recensioni'">
        <ion-list-header>
          <div id="avg">
            <div>
              <span item-start text-wrap>Voto Google: </span>
              <span item-end text-wrap class="end" *ngIf="navParams.get('rating') != undefined">{{navParams.get('rating')}}/5</span>
              <span item-end text-wrap class="end" *ngIf="navParams.get('rating') == undefined">Nessuna valutazione!</span>
            </div>
            <div>
              <span item-start text-wrap class="start">Voto Tripadvisor: </span>
              <ion-spinner item-end text-wrap class="end" *ngIf="!loaded" name="dots"></ion-spinner>
              <span item-end text-wrap class="end" *ngIf="loaded && rating != undefined">{{rating}}/5</span>
              <span item-end text-wrap class="end" *ngIf="loaded && rating == undefined">Nessuna valutazione!</span>
            </div>
          </div>
        </ion-list-header>
        <ion-list>
          <ion-item *ngFor="let recensione of reviews">
            <div class="center">
              <ion-avatar>
                <img [src]="recensione.profile_photo_url">
              </ion-avatar>
            </div>
            <p class="name">{{recensione.author_name}}</p>
            <div class="rating">
              <div class="star-ratings-sprite">
                <span [style.width]="(100*recensione.rating/5) + '%'" class="star-ratings-sprite-rating"></span>
              </div>
            </div>
            <div *ngIf="recensione.title != undefined" class="title">
              <span text-wrap>{{recensione.title}}</span>
            </div>
            <span class="review" text-wrap>{{recensione.text}}</span>
            <div class="date">
              <p>{{recensione.relative_time_description}}</p>
            </div>
          </ion-item>
        </ion-list>
        <ion-spinner *ngIf="!loaded"></ion-spinner>
        <ion-infinite-scroll (ionInfinite)="scrapeNext($event)" threshold="1000px">
          <ion-infinite-scroll-content></ion-infinite-scroll-content>
        </ion-infinite-scroll>
      </div>
    </div>
  </div>
</ion-content>

In this page I show infos and reviews about a specific restaurant (the reviews are displayed inside the ion-list). To retrieve the reviews I used the following code in the .ts file:

this.scraper.getTaReviews(this.navParams.get('name'))
  .subscribe(data => {
    console.log(data)
    if (data != "no data") {
      this.placeId = data.placeId;
      this.risId = data.risId;
      this.hasNext = data.hasNext;
      this.rating = data.avgRating;
      this.reviews = this.reviews.concat(data.reviews);
      console.log(this.reviews);
    }
    this.loaded = true;
  })

Obviously I initiated the reviews variable to be an empty array in the constructor.

This is the function that is called to make the http call:

 getTaReviews(ris: string) {
    let request = this.http.get(this.hostname + ':8090/tarev?ris=' + ris + '&citta=' + this.share.getProvincia()).map(res => res.json()).retry();
    return this.cache.loadFromObservable(ris + "-" + this.share.getProvincia(), request);
    // return this.http.get(this.hostname + ':8090/tarev?ris=' + ris + '&citta=' + this.share.getProvincia()).map(res => res.json()).retry();
  }

The uncommented part is the new one, and the commented part is the old working one. My problem is that the first time I open the page and get the data, everything works just fine and the reviews in the ion-list are displayed correctly. When I use cached data, however, the ion-items inside the list are not populated, even though the reviews array contains the correct data (I checked it in the console log). As I said before, it works just fine if I don't use ionic-cache, but I can't really explain why this behaviour affects only this page. Moreover, all the other cached data (except from the reviews) is displayed correctly, it looks like it is a problem just with the ngFor statement.

lpeppe commented 7 years ago

Well I managed to solve this problem, but it is still kinda weird. It works perfectly if I add a timeout in this way:

this.scraper.getTaReviews(this.navParams.get('name'))
      .subscribe(data => {
        console.log(data)
        if (data != "no data") {
          this.placeId = data.placeId;
          this.risId = data.risId;
          this.hasNext = data.hasNext;
          this.rating = data.avgRating;
          setTimeout(_ => this.reviews = this.reviews.concat(data.reviews), 1000);
          console.log(this.reviews);
        }
        this.loaded = true;
      })

Hope this can help someone

Nodonisko commented 6 years ago

Not sure where could be problem. Please comment here or open new issue if anyone will experience same problem.