离子2 - 在无限滚动中过滤搜索

时间:2017-01-04 17:06:33

标签: typescript ionic2 infinite-scroll pouchdb searchbar

我正在使用PouchDB作为数据库,我已经在我的项目中实现了无限滚动。对于第一次加载,将只显示40个文档,对于下一个滚动,它将加载40个文档。我的数据库中的总文档大约是3000个文档。我做无限滚动时没有问题,但是我通过使用无限滚动在过滤数据中遇到问题。我可以搜索已经显示/查看的数据但我无法搜索未查看的数据。它只能过滤已加载的数据。以下是我的代码。

providers.ts

constructor(public http: Http) {


this.db = new PouchDB('location');
console.log('Hello User Provider',this.db);
this.remote = 'http://data/location';

let options = {
    live: true,
    retry: true
};

this.db.sync(this.remote, options)
  .on('change', function(change){
    console.log('Users provider change!', change);
  })
  .on('paused', function(info){
    console.log('Users provider paused!', info);
  })
  .on('active', function(info){
    console.log('Users provider active!', info);
  })
  .on('error', function(err){
    console.log('users provider error!', err)
  });

}

getUsers(skip,limit){

var total;

return new Promise(resolve => {

  this.db.info().then(function (info) {

    total = info.doc_count;
  })


  this.db.allDocs({
    include_docs: true,
    descending:true,
    limit: limit,
    skip:skip
  })
  .then((result) => {
    this.data = [];

      result.rows.map((row) => {
        if(row.doc._id.substring(0,8) !== '_design/'){
          this.data.push(row.doc);
        }
      })


    resolve(this.data);

    this.db.changes({live: true, since: 'now', include_docs: true})
    .on('change', (change) => {
      this.handleChange(change);
    })

  })
  .catch((error) => {

    console.log('Error when getUsers!', error);

  })

})

}

home.html

<ion-content class="sample-modal-page">
  <ion-searchbar (ionInput)="getItems($event)">
  </ion-searchbar>
  <ion-item *ngFor = "let user of users (click)="dismiss(user.Description)">
    <h3>{{user.Description}}</h3>
    <h4>{{user.code}}</h4>
    <h4>{{user.branch}}</h4>
  </ion-item>

  <ion-infinite-scroll (ionInfinite)="doInfinite($event)">
    <ion-infinite-scroll-content
      loadingSpinner="bubbles"
      loadingText="Loading more data...">
    </ion-infinite-scroll-content>
  </ion-infinite-scroll>

home.ts

users: any = [];
staff: any = [];
searchQuery: string = '';

skip : any = 0;
limit : any = 40;

constructor(public user: User,public loadingCtrl: LoadingController, public viewCtrl: ViewController, public navCtrl: NavController, public navParams: NavParams)
{
  let loadingPopup = this.loadingCtrl.create({
    content: 'Loading data...'
  });

  loadingPopup.present();

  //get data from user provider
  this.user.getUsers(this.skip,this.limit).then(data => {

    this.staff = data;

    this.initializeItems();

    loadingPopup.dismiss();
  });
}

initializeItems() {

  this.users = this.staff;
}

getItems(ev) {

  this.initializeItems();

  var val = ev.target.value;

  if (val && val.trim() != '') {
    this.users = this.users.filter((user) => {

      return (user.Description.toLowerCase().indexOf(val.toLowerCase()) > -1);
    })
  }
}

doInfinite(infiniteScroll){

  setTimeout(() => {

    this.skip = this.skip + this.limit;

    this.user.getUsers(this.skip,this.limit).then((data) => {

      for (var i = 0; i < this.limit; i++) {
        this.users.push(data[i]);
        console.log('Apa ini sebenarnya',this.users);
      }

    });

    console.log('Sync end');
    infiniteScroll.complete();
  },250);
}

2 个答案:

答案 0 :(得分:0)

从您的代码中,您通过发送额外参数来调用查询,该参数是skip和limit。这意味着每个查询只能获得40个数据。

  1. 如果要在客户端进行过滤(例如数据表),则需要获取所有数据,而不是在客户端进行操作(过滤,分页)

  2. 如果您想坚持自己的方式(发送限制和跳过参数查询功能),您也必须发送过滤器,然后重置限制并跳过参数为0

答案 1 :(得分:0)

最近我遇到了同样的问题,我将从一开始就说明解决方案。

离子2和3具有相同的过程。

1。无限滚动

使用Ionic文档呈现列表非常简单: https://ionicframework.com/docs/v3/api/components/infinite-scroll/InfiniteScroll/

2。搜索栏

同样,请按照Ionic文档配置搜索栏: https://ionicframework.com/docs/v3/api/components/searchbar/Searchbar/

3。管道

最好使用管道过滤元素,您将能够在模板,控制器和模板中同时使用它,并将其在其他组件中重复使用。

对于不需要无限滚动的小列表,我将其直接放在模板中:

<ion-list>                                                                                                                                                                     
  <button *ngFor="let item of items | search : searchbarValue:searchbarFilters">

对于控制器中较长的情况:

let filteredOptions = new SearchPipe().transform(this.items, this.searchbarValue, this.searchbarFilters);

我的真实案例

在我的情况下,this.items包含2.000个值,因此我无法渲染它们,因此我将使用无限滚动仅渲染已过滤的元素。

我粘贴自己的代码,向您展示它们的外观。

template.html

<ion-searchbar                                                                                                                                                               
  [placeholder]="searchbarPlaceholder"                                                                                                                                       
  (ionInput)="onSearch($event)"                                                                                                                                              
  [(ngModel)]="searchbarValue">                                                                                                                                              
</ion-searchbar>

<!-- List filtered elements -->
<ion-list>                                                                                                                                                                     
  <button *ngFor="let item of filteredItems">

controller.ts

dynamicOffset: number = 0;
dynamicLimit: number = 30;
offset: number = 0;
limit: number = 30;

/**
 * This function is called when some new value is placed in the searchbar.
 * I have two arrays:
 * - Original list with 2.000 values (this.items)
 * - Filtered list empty (this.filteredItems)
 */
onSearch(): void {
  // on every search I reset my filtered list                                                                                                                                                       
  this.filteredItems.length = 0;
  // I call the pipe passing by parameter the ORIGINAL list of items,
  // the searchbarValue and the properties to look them for.
  // I receive the filtered items.
  let filteredItems = new SearchPipe().transform(this.items, this.searchbarValue, this.searchbarFilters);                                                                  
  // I reset the limits of the infinite scroll because I will be filtering in a new list
  this.dynamicOffset = this.offset;                                                                                                                                            
  this.dynamicLimit = this.limit;                                                                                                                                                                                                                                                                                                                             

  this.loadItems(filteredItems);                                                                                                                                           } 

/**                                                                                                                                                                            
* Load items.                                                                                                                                                                 
*/                                                                                                                                                                            
loadItems(items: any = []): void {                                                                                                                                           
  let item;                                                                                                                                                                    
  while (this.dynamicOffset < this.dynamicLimit) {                                                                                                                             
    item = items[this.dynamicOffset];                                                                                                                                        
    if (!item) break;                                                                                                                                                          
    this.filteredItems.push(item);                                                                                                                                           
    this.dynamicOffset++;                                                                                                                                                      
  }

  this.dynamicLimit = this.dynamicLimit + this.limit;                                                                                                                          
}

无论如何,这是一个解决问题的方法。还有更多选择,但就我而言,此代码解决了我的后顾之忧。