0

I created sorting sidebar which filter my product list based on category and price. Filtering by category works correctly. sidebar I have a problem with filtering based on the price of the product.If I set the category to "Smartfons" and filter a product with a price higher than 2000, it will return Iphone X correctly in my case:Price more than 2000 but when I change the filter to "All" I have this one phone and It should return 3 phones:All smartfons

    export class ProductComponent implements OnInit {
  filteredProduct: Products[] = [];
  products: Products[] = [];
  currentSorting: string;
  wrapper = true;
  @ViewChild('filtersComponent')
  filtersComponent: SortProductsComponent;

  constructor(protected productsService: CategoriesProductsService) { }

    sortFilters: any[] = [
      { name: 'Name (A to Z)', value: 'name' },
      { name: 'Price (low to high)', value: 'priceAsc' },
      { name: 'Price (high to low)', value: 'priceDes' }
    ];
    priceFilters: any[] = [
      { name: 'All', value: 'all', checked: true },
      { name: 'Price > 2000', value: 'more_2000', checked: false },
      { name: 'Price < 500', value: 'less_500', checked: false }
    ];

  ngOnInit() {
    this.displayProducts();
  }
  displayProducts() {
    this.productsService.getProducts().subscribe(product => {
      this.products = product;
      this.filteredProduct = product; });
    }

    onFilterChange(data) {
      if (data.type === 'category') {
      if (data.isChecked) {
          // tslint:disable-next-line:prefer-for-of
          for (let i = 0; i < data.filter.Products.length; i++) {
          this.filteredProduct.push(data.filter.Products[i]);
          }
        } else {
          this.filteredProduct =
          this.products.filter(x => {
            return x.CategoryId !== data.filter.Id; } );
        }
      } else if (data.type === 'price') {
        this.filteredProduct = this.products;
        if (data.isChecked) {
          const priceFilter = data.filter.value;
          if (priceFilter === 'all') {
              this.filteredProduct = this.products;
          } else if (priceFilter === 'more_2000' ) {

              this.filteredProduct = this.products.filter(x => x.Price > 2000);

          } else if (priceFilter === 'less_500' ) {

                this.filteredProduct = this.products.filter(x => x.Price < 500);
          }
        }
      }
    }

SortProductComponent:

   export class SortProductsComponent implements OnInit {
  categoriesList: Categories[];
  @Input()
  priceFilters: any[];
  // tslint:disable-next-line:no-output-on-prefix
  @Output()
  onFilterChange = new EventEmitter<any>();
  showFilters = true;
  sideShown = false;
  constructor(private categoriesService: CategoriesProductsService) { }

  ngOnInit() {
    this.displayCategories();
  }
  displayCategories() {
    this.categoriesService.getCategories().subscribe((data) => {
     this.categoriesList = data;

    });
  }
  onInputChange($event, filter, type) {
    const change = $event.target.checked ? 1 : -1;
    this.onFilterChange.emit({
      type,
      filter,
      isChecked: $event.target.checked,
      change
    });
}
}

HTML template:

   <h5>Filter by categories</h5>
  <form >
      <div class="category-filter filter-wrapper" *ngFor = 'let filter of categoriesList'>
        <div class="custom-control custom-checkbox">
            <label class="fake-checkbox">
              <input type="checkbox" class="custom-control-input" checked (change)='onInputChange($event, filter, "category")'>
              <span class="custom-control-label">  {{filter.Name}}</span>
              <span></span>
            </label>
        </div>
    </div>
</form>
<h5>Filter by price</h5>
<form *ngIf = "showFilters">
    <div class="custom-filter filter-wrapper" *ngFor = 'let filter of priceFilters'>
        <label class="fake-checkbox">
          <input type="radio" name="price" [checked]='filter.checked' (click)='onInputChange($event, filter, "price")'>
          <span class="circle"><span class="fill"></span></span>
          <span class="label">{{filter.name}}</span>
          <span></span>
        </label>
    </div>
  </form>

Product class:

export class Products {
  Id: number;
  Name: string;
  Description: string;
  DetailedDescription: string;
  Price: number;
  IsNewProduct: boolean;
  PromotionalProduct: boolean;
  Image: string;
  CategoryId: number;
}

I think that by using the filter () method, which returns a new array to me, the filter on the array works only once.

I would like my category and price filter to work just like on this page: https://carlosroso.com/angular2-shop

Any help is welcome

1 Answer 1

1

Yes, unless you want to re-get the products every time the user changes the filter, you'll need to retain the list of original products (unfiltered) and use it to filter your list.

Here is what my code looks like:

  ngOnInit(): void {
    this.productService.getProducts().subscribe(
      products => {
        this.products = products;
        this.filteredProducts = this.products;
      },
      error => this.errorMessage = <any>error
    );
  }

Notice that it is retaining the returned values from the service both in products, which is the complete list and filteredProducts which will always be the filtered list. (Though it is originally the full list of products assuming the display starts with no filters.)

Then the source of the filter is always the original list:

  performFilter(filterBy: string): IProduct[] {
    filterBy = filterBy.toLocaleLowerCase();
    return this.products.filter((product: IProduct) =>
      product.productName.toLocaleLowerCase().indexOf(filterBy) !== -1);
  }

Notice that it uses this.products.filter to ensure it always starts filtering from the full list of products.

Yours would looks something more like:

      this.filteredProduct = this.products.filter(x => {
        return x.CategoryId !== data.filter.Id; } );
    }
Sign up to request clarification or add additional context in comments.

4 Comments

I updated my post of your recommendations but I still have problem with price filter: zapodaj.net/b7883f722551d.png.html
What problem are you having?
My price filter works correctly when all categories are selected.When I selected "Smartfons" categories and I chose the filter price less than 500 it showed me products from the entire list, a should display an empty list, because there is no such product in this selected category. Just like in this picture that I put above.
Try talking through every line of your onFilterChange method and ensure you are working with the appropriate set of data at each step. I don't know enough about what that code is attempting to achieve in each line to help more.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.