【问题标题】:How to filter using a toggle button in Angular如何使用 Angular 中的切换按钮进行过滤
【发布时间】:2019-05-16 12:02:41
【问题描述】:

我正在尝试使用 ngFor 显示一些数据。我想使用切换对显示的数据进行过滤。

到目前为止,我已经使过滤器部分工作。目前,当我单击切换时,它确实过滤了我的数据。例如:当我点击切换“健身房”时,它会返回所有有健身健身房的房子。但是当我点击说多个切换时它不会过滤房屋,例如当我点击“健身房”和“Wifi”时它应该返回一个包含便利设施的房屋列表:健身房和 Wifi

我希望过滤器在我点击多个切换按钮时返回一个房屋列表,例如当我点击“健身房”和“Wifi”时它应该返回一个带有舒适设施的房屋列表:健身房和 Wifi

我的组件是:

import { Component, OnInit } from '@angular/core';
import { Home } from '../../models/IHome.model';


@Component({
  selector: 'app-search',
  templateUrl: './homes.component.html',
  styleUrls: ['./homes.component.css']
})

export class HomesComponent implements OnInit {

  defaultSelection = 'All';
  searchText: any;
  address: string;
  counter = 0;
  homes: Home[];

  filterArgs: any = { type: '', address: '', car_type: '', amenity: '' };


  amenities = [
    {
      'name': 'Wifi',
      'value': false
    },
    {
      'name': 'Gym',
      'value': false
    },
    {
      'name': 'Swimming Pool',
      'value': false
    },
    {
      'name': 'Garden',
      'value': false
    }
  ];

  constructor() { }

  ngOnInit() {
    this.homes = [
      {
        'id': 1,
        'type': 'Villa',
        'price': 920000,
        'address': 'CMC',
        'area': 6292,
        'bedrooms': 2,
        'bathrooms': 2,
        'car_type': 'Cars',
        'park_spots': 1,
        'amenity': ['Gym'],
        'homeUrl': '../../assets/ezembil10.jpg'
      },
      {
        'id': 2,
        'type': 'Apartment',
        'price': 3000,
        'address': 'Summit',
        'area': 921,
        'bedrooms': 3,
        'bathrooms': 1,
        'car_type': 'Cars',
        'park_spots': 2,
        'amenity': ['Wifi'],
        'homeUrl': '../../assets/ezembil6.jpg'
      },
      {
        'id': 3,
        'type': 'Villa',
        'price': 820000,
        'address': 'Hayat',
        'area': 4921,
        'bedrooms': 2,
        'bathrooms': 2,
        'car_type': 'Trucks',
        'park_spots': 3,
        'amenity': ['Garden', 'Swimming Pool'],
        'homeUrl': '../../assets/ezembil8.jpg'
      },
      {
        'id': 4,
        'type': 'Apartment',
        'price': 420000,
        'address': 'Sarbet',
        'area': 3921,
        'bedrooms': 2,
        'bathrooms': 3,
        'car_type': 'Cars',
        'park_spots': 4,
        'amenity': ['Swimming Pool'],
        'homeUrl': '../../assets/ezembil1.jpg'
      },
      {
        'id': 5,
        'type': 'Villa',
        'price': 629000,
        'address': 'Mekhanisa',
        'area': 2921,
        'bedrooms': 1,
        'bathrooms': 1,
        'car_type': 'Vans',
        'park_spots': 1,
        'amenity': ['Gym'],
        'homeUrl': '../../assets/ezembil6.jpg'
      },
      {
        'id': 6,
        'type': 'Apartment',
        'price': 720000,
        'address': 'Bole',
        'area': 1921,
        'bedrooms': 3,
        'bathrooms': 3,
        'car_type': 'Bikes',
        'park_spots': 1,
        'amenity': ['Gym'],
        'homeUrl': '../../assets/ezembil5.jpg'
      }
    ];

  }

  amenityChange(item: any, e: any) {
    if (e.srcElement.checked === true) {
      console.log('checked');
      for (let i = 0; i < this.amenities.length; i++) {
        if (this.amenities[i].name === item) {
          this.amenities[i].value = true;
        }
      }
    }
    if (e.srcElement.checked === false) {
      console.log('unchecked');
      this.counter = 0;
      for (let i = 0; i < this.amenities.length; i++) {
        if (this.amenities[i].name === item) {
          this.amenities[i].value = false;
        }
      }
    }
    for (let j = 0; j < this.amenities.length; j++) {
      if (this.amenities[j].value === true) {
        this.filterArgs.amenity = this.amenities[j].name;
        this.counter = 1;
      }
    }
    if (this.counter === 0) {
      this.filterArgs.amenity = '';
    }
  }

}

我的管道是:

import { Pipe, PipeTransform } from '@angular/core';
import { Home } from '../models/IHome.model';

@Pipe({
    name: 'amenitiesFilter',
    pure: false
})

export class AmenitiesFilterPipe implements PipeTransform {

    transform(values: any[], filter: Home): any {
        /* console.log('amenities', values, filter); */
        if (!values || !filter || !filter.amenity) {
            return values;
        }
        return values.filter(item => {
            return item.amenity.indexOf(filter.amenity) !== -1;
        });
    }
}

我的模板是:

 <p *ngFor="let amenity of amenities">
   <label>{{ amenity.name }}</label>
   <label class="switch">
     <input type="checkbox" id={{amenity.name}} name="amenities" (change)="amenityChange(amenity.name, $event)">                      
     <span class="toggle round"></span>
   </label>
 </p>

  <ng-container *ngFor="let home of homes  | amenitiesFilter: filterArgs  
      | pricerangeFilter: 'price': min:max       
      | paginate: { itemsPerPage: 6, currentPage: p } ">

            <div class="homes" (click)="openDetails()">
                <img class="homes_content" src="{{ home.homeUrl }}" /><br>
                <div class="labels">
                    <label><i class="fa fa-map-marker fa-fw" aria-hidden="true"></i>&nbsp;{{ home.address }}</label><br>
                    <label><i class="fa fa-money fa-fw"
              aria-hidden="true"></i>&nbsp;{{ home.price | currency:"USD":"symbol" : "1.0"}}</label>
                </div>
                <hr>
                <button class="details"><i class="fa fa-tag fa-fw" aria-hidden="true"></i>&nbsp;{{ home.type }}</button>
                <label>&nbsp;SqFt:{{ home.area }}</label><br>
            </div>

   </ng-container>
   <pagination-controls (pageChange)="p= $event" style="float:right"></pagination-controls>

【问题讨论】:

    标签: angular


    【解决方案1】:

    我对你的代码做了一些修改.. 不要使用管道

    homes: Home[];
     homesFiltered:Home[];
    
      filterArgs: any = { type: '', address: '', car_type: '', amenity: '' };
    
    
      amenities = [
        {
          'name': 'Wifi',
          'value': false
        },
        {
          'name': 'Gym',
          'value': false
        },
        {
          'name': 'Swimming Pool',
          'value': false
        },
        {
          'name': 'Garden',
          'value': false
        }
      ];
    
      constructor() { }
    
      ngOnInit() {
        this.homes = [
          {
            'id': 1,
            'type': 'Villa',
            'price': 920000,
            'address': 'CMC',
            'area': 6292,
            'bedrooms': 2,
            'bathrooms': 2,
            'car_type': 'Cars',
            'park_spots': 1,
            'amenity': ['Gym'],
            'homeUrl': '../../assets/ezembil10.jpg'
          },
          {
            'id': 2,
            'type': 'Apartment',
            'price': 3000,
            'address': 'Summit',
            'area': 921,
            'bedrooms': 3,
            'bathrooms': 1,
            'car_type': 'Cars',
            'park_spots': 2,
            'amenity': ['Wifi'],
            'homeUrl': '../../assets/ezembil6.jpg'
          },
          {
            'id': 3,
            'type': 'Villa',
            'price': 820000,
            'address': 'Hayat',
            'area': 4921,
            'bedrooms': 2,
            'bathrooms': 2,
            'car_type': 'Trucks',
            'park_spots': 3,
            'amenity': ['Garden', 'Swimming Pool'],
            'homeUrl': '../../assets/ezembil8.jpg'
          },
          {
            'id': 4,
            'type': 'Apartment',
            'price': 420000,
            'address': 'Sarbet',
            'area': 3921,
            'bedrooms': 2,
            'bathrooms': 3,
            'car_type': 'Cars',
            'park_spots': 4,
            'amenity': ['Swimming Pool'],
            'homeUrl': '../../assets/ezembil1.jpg'
          },
          {
            'id': 5,
            'type': 'Villa',
            'price': 629000,
            'address': 'Mekhanisa',
            'area': 2921,
            'bedrooms': 1,
            'bathrooms': 1,
            'car_type': 'Vans',
            'park_spots': 1,
            'amenity': ['Gym'],
            'homeUrl': '../../assets/ezembil6.jpg'
          },
          {
            'id': 6,
            'type': 'Apartment',
            'price': 720000,
            'address': 'Bole',
            'area': 1921,
            'bedrooms': 3,
            'bathrooms': 3,
            'car_type': 'Bikes',
            'park_spots': 1,
            'amenity': ['Gym'],
            'homeUrl': '../../assets/ezembil5.jpg'
          }
        ];
    this.homesFiltered=this.homes;
      }
    
    
        amenityChange(amenity) {
          amenity.value=!amenity.value;
          let filterBy= this.amenities.filter((x)=>x.value==true).map((v)=>{
             return  v.name;
            });
    
          if(filterBy && filterBy.length){
            this.homesFiltered=this.homes.filter((x)=>x.amenity.some(r=> filterBy.indexOf(r) >= 0))
          }else{
            this.homesFiltered=this.homes;
          }
        }
    

    并在 html 中将复选框更改为:

    <input type="checkbox" id={{amenity.name}} [checked]="amenity.value" name="amenities" (change)="amenityChange(amenity)">    
    

    【讨论】:

      【解决方案2】:

      我会放弃这种过滤的管道方法。对于简单的功能,那里的代码太多...

      amenityChange() 上,添加一些代码以通过具有真实价值的所选设施过滤房屋。将组件上的结果保存为filteredHomes,并循环通过filteredHomes 而不是homes。删除与过滤相关的所有其他内容以及为该管道提供服务的所有内容。

      例如;

      filteredHomes = homes;
      .
      .
      .
      
      amenityChange(item: any, e: any) {
          if (e.srcElement.checked === true) {
            console.log('checked');
            for (let i = 0; i < this.amenities.length; i++) {
              if (this.amenities[i].name === item) {
                this.amenities[i].value = true;
              }
            }
          }
          if (e.srcElement.checked === false) {
            console.log('unchecked');
            this.counter = 0;
            for (let i = 0; i < this.amenities.length; i++) {
              if (this.amenities[i].name === item) {
                this.amenities[i].value = false;
              }
            }
          }
      
          let filteredAmenities = this.amenities.filter(a => a['value'] == true);
          if (filteredAmenities.length == 0){
              this.filteredHomes = homes;
          }
          else{
              this.filteredHomes = [];
              for (let fa of filteredAmenities){
                  this.filteredHomes = this.homes.filter(h => h['amenity'].indexOf(fa['name']) > -1)
                  .concat(this.filteredHomes);
              }
              //Here you can remove duplicates however you like, here's an example with lodash
              this.filteredHomes = _.uniqBy(this.filteredHomes, 'id');
              }
          }
      

      顺便说一句,如果您将每个复选框绑定到一个属性并使用类型,您将能够删除 amenityChange() 的第一部分。

      【讨论】:

      • 我选择将每个复选框绑定到一个属性并按照你的建议使用类型,它工作得很好。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-26
      • 2018-12-07
      • 1970-01-01
      相关资源
      最近更新 更多