简体   繁体   中英

How to filter results for range slider with multiple checkbox together in Angular 2?

I am trying to filter results for the given array "db", there are three filters: price, duration, and category.

I tried using filter() method to filter results.

Here is the link of code which i have tried: https://stackblitz.com/edit/multiple-filters?file=app%2Fapp.component.ts

component.html

<div class="filters">
  <div id="price">
  <h3>Price: {{rangeValues[0] + ' - ' + rangeValues[1]}}</h3>
  <p-slider [(ngModel)]="rangeValues" (click)="handleChange()" [min]="0" 
  [max]="2000" [style]="{'width':'14em'}" [range]="true"></p-slider>
</div>
<hr>
<div id="duration">
    <h3>Duration</h3>
    <li><input type="checkbox" (click)="checkFilter('2 days')"> 2 Days</li>
    <li><input type="checkbox" (click)="checkFilter('6 days')">6 Days</li>
</div>
<hr>
<div id="Theme">
    <h3>Theme</h3>
    <li><input type="checkbox" id="Wild Life" (click)="filterTheme('Wild Life')">Wild Life</li>
    <li><input type="checkbox" id="Romance" (click)="filterTheme('Romance')">Romance</li>
    <li><input type="checkbox" id="Food & Drink" (click)="filterTheme('Food & Drink')">Food & Drink</li>
    <li><input type="checkbox" id="Adventure" (click)="filterTheme('Adventure')">Adventure</li>
 </div>
 <hr>
 </div>

 <div class="results">
    <h3>Results</h3>

    <div *ngFor="let p of package">
    <p>{{p.product_name}}</p>
    </div>
 </div>

component.ts

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
 db=[
{
  "id":"1",
  "product_name":"6 Days at Karnataka",
  "price":324,
  "duration":"6 days",
  "category":["Romance"]
},
{
  "id":"5",
  "product_name":"2 Days at Thailand",
  "price":234,
  "duration":"2 days",
  "category":["Romance","Wild Life"]
},
{
  "id":"8",
  "product_name":"2 Days at Delhi",
  "price":1400,
  "duration":"2 days",
  "category": ["Romance","Food & Drink","Adventure"],
}
];
rangeValues: number[] = [0,2000];
package:any;
filterData=[];


ngOnInit(){
  this.packageList();
}

packageList(){
 for(let i = 0; i < this.db.length; i++){
  this.filterData.push(this.db[i]);
  this.package =this.filterData;
 }    
}

handleChange() {
        for(let i = 0; i < this.filterData.length; i++){             
          this.package= this.filterData.filter(item => item.price >=this.rangeValues[0] && item.price <=this.rangeValues[1]);
   }
}

checkFilter(id){ 
    if(id.checked==true){
      for(let i = 0; i < this.filterData.length; i++){
         this.filterData= this.filterData.filter(item => item.duration !== id && item.price >=this.rangeValues[0] && item.price <=this.rangeValues[1]);
          this.package=this.filterData;
      }
    }
    else {
      for(let i = 0; i < this.filterData.length; i++){
          this.filterData= this.filterData.filter(item => item.duration == id && item.price >=this.rangeValues[0] && item.price <=this.rangeValues[1]);
          this.package=this.filterData;
      }
    }
 }


filterTheme(id){
    let b=(<HTMLInputElement>document.getElementById(id));
    if(b.checked==true){
      for(let i = 0; i < this.filterData.length; i++){
        for(let j=0;j< this.filterData[i].category.length; j++){
          if(this.filterData[i].category[j]==id &&  this.filterData[i].price >=this.rangeValues[0] &&  this.filterData[i].price <=this.rangeValues[1]){

            this.package= this.filterData.filter(item => item.category[j]==id && item.price >=this.rangeValues[0] && item.price <=this.rangeValues[1]);
          }
        }
      }
    }else {
      for(let i = 0; i < this.filterData.length; i++){
        for(let j=0;j<this.filterData[i].category.length; j++){
          if(this.filterData[i].category[j]!==id && this.filterData[i].price >=this.rangeValues[0] && this.filterData[i].price <=this.rangeValues[1]){
            this.package = this.filterData.filter(item => item.category[j]!== id && item.price >=this.rangeValues[0] && item.price <=this.rangeValues[1]);

          }
        }
      }
    }

 }

}

What I want to achieve:

  1. price filter: which I have used the range slider to filter results and it filters price correctly but it should also filter results for selected duration and category.

  2. Duration filter: used the checkbox to filter results, this should filter results for the given price and selected category.

  3. Category filter: one product_name can have one or more category and it should filter results for the selected one and price chosen.

Well, you are complicating the things by looping over it and checking it you can have one function that would do the work for you.

step1: Take 3 models

rangeValues: number[] = [0, 2000];
  durations: any = [];
  themes: any = [];

step2 : assign the values of the user in these models

  handleChange() {
    this.ApplyFilters();
  }

  checkFilter(id) {
    if (this.durations.some(a => a === id)) {
      this.durations = this.durations.filter(a => a !== id)
    } else {
      this.durations.push(id)
    }
    this.ApplyFilters();
  }


  filterTheme(id) {
    if (this.themes.some(a => a === id)) {
      this.themes = this.themes.filter(a => a !== id)
    } else {
      this.themes.push(id)
    }
    this.ApplyFilters();
  }

step3 : Create one common filter

  ApplyFilters() {
    this.package = this.filterData.filter(item => {
      return (item.price >= this.rangeValues[0] && item.price <= this.rangeValues[1]) && (this.durations.some(b => b === item.duration) || this.durations.length === 0) && (item.category.every(c => this.themes.some(d => d === c)) || this.themes.length === 0)
    });
  }

And your are done

Here is the demo

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM