ngx-infinite-scrollの表示ロジックについて

Who αm I?

この4月からAngularを触っております。
香川県のエンジニアです。

讃岐うどんが大好きだ!
というサービスをAngularを利用してリリースしました。
(まだまだ、未熟なサイトなので暖かい目でみていただけると幸いです。)

解決したい課題

トピックに書かせていただいている通り、ngx-infinite-scrollを利用した、データの読み込みをしたいと考えております。

実際に、このリンクではinfinite-scrollを実装できているのですが、こちらは、クエリパラメータがなく、全件取得なので、for文でindex番号を順番に利用してAPIにデータを取得しに行っており、スクロールしたらまた、そのfor文の続きから、データを取得するだけのシンプルな処理になります。

下記具体的なサンプルです。

infinite-scrollのHTML部分

<div
  class="serach-result"
  infiniteScroll
  [infiniteScrollDistance]="4"
  [infiniteScrollThrottle]="100"
  (scrolled)="onScroll()"
  >
   〜〜あああ
 </div>
    // クエリパラメータの取得
    const areaOption = this.route.snapshot.queryParams.area;
 
 // 最初に取得する件数を指定
    const limit = 12;

 // エリア指定がない場合は12件取得する
    if (areaOption === undefined) {
      for (let i = 1; i < 13; i++) {
        this.restaurantService.fetchRestaurantById(i)
        .subscribe((data) => {
          this.restaurants.push(data);
        });
      }
    }

onScrollの処理

  onScroll() {
    if (this.notscrolly && this.notEmptyRestaurant) {
      this.spinner.show();
      this.notscrolly = false;
      this.loadNextRestaurant();
    }
  }

loadNextRestaurant()の処理

  loadNextRestaurant() {
      const lastRestaurantId = this.restaurants.length;
     // 次の12件を取得する
      for (let i = lastRestaurantId; i < lastRestaurantId + 12; i++) {
        this.restaurantService.fetchRestaurantById(i)
        .subscribe((data) => {
          this.restaurants = this.restaurants.concat(data);
          this.spinner.hide();
        });
      }
      if (this.restaurants.length === 件数) {
        this.notEmptyRestaurant = false;
        this.spinner.hide();
      }
      this.notscrolly = true;
    }
  }
}

上記のような処理を書いており、思ったように動いてはおります。

さて、前置きが長くなってしまいました。。。
次に例えばこのリンクのようにエリアのパラメータがついて先のsearch-resultでinfiniteスクロールを実装しようと思った場合、loadNextRestaurant()のうまい処理が思い浮かびませんでした。

高松市のデータで、最初に取得した物から続きのデータを取得する方法を考えているのですが何か良い手段はありますでしょうか?

その他のサイトで確認はしたのですが、有益な情報が見つからず、もしご利用の方がいれば、こうした方がいいよとアドバイスいただけると幸いです。

もとのデータソースがそもそもページネーションに対応していないのであれば他に方法はないように思います。
あるいは事前にデータを集めておいてページネーション可能な自前のAPIを作るとかでしょうかね…

1 Likes

ご返信いただきありがとうございます。
はい、元のAPIも自作の物でありJSONをただ返すだけですね。。

あるいは事前にデータを集めておいてページネーション可能な自前のAPIを作るとかでしょうかね…

今回のサービスはよくも悪くもデータ個数が限定的なので、先にハードコードでIDリストなどを作成しておき、そこを参照しながらデータアクセスを実装するなど試してみます。

@lacolaco

以前は、本件についてコメントをいただきありがとうございました。

こちら、解決案として、最後はサーバーサイドに、pageと連動したクエリパラメータを設置して、offsetとlimitを利用して対応する方針となりました。
(NestJS x TypeORMによるバックエンドでしたので、skip、take部分の記述です。)

レベルは低いですが、少しでも誰かの役に立てば幸いです。

let photos = await connection
    .getRepository(Photo)
    .createQueryBuilder("photo") // first argument is an alias. Alias is what you are selecting - photos. You must specify it.
    .innerJoinAndSelect("photo.metadata", "metadata")
    .leftJoinAndSelect("photo.albums", "album")
    .where("photo.isPublished = true")
    .andWhere("(photo.name = :photoName OR photo.name = :bearName)")
    .orderBy("photo.id", "DESC")
    .skip(5)
    .take(10)
    .setParameters({ photoName: "My", bearName: "Mishka" })
    .getMany();

参考リンク
https://typeorm.io/#/

2 Likes