Filters

Angular Bootstrap 5 Filters plugin

Filters are the best way to select data that meets your requirements - they affect your search results by filtrating and sorting the dataset you pass to our component.

View full screen demo

Basic example

Filter: Color
Filter: Sale
        
            
          <div class="container">
            <form [formGroup]="filtersGroup">
              <div class="col-md-6">
                <span class="fa-lg">Filter: Color</span>
  
                <div class="form-check mt-3">
                  <input
                    mdbInput
                    class="form-check-input"
                    type="radio"
                    name="color"
                    id="arrayRadio1"
                    value="black"
                    formControlName="color"
                  />
                  <label class="form-check-label" for="arrayRadio1">Black</label>
                </div>
  
                <div class="form-check">
                  <input
                    mdbInput
                    class="form-check-input"
                    type="radio"
                    name="color"
                    id="arrayRadio2"
                    value="red"
                    formControlName="color"
                  />
                  <label class="form-check-label" for="arrayRadio2">Red</label>
                </div>
  
                <div class="form-check">
                  <input
                    mdbInput
                    class="form-check-input"
                    type="radio"
                    name="color"
                    id="arrayRadio3"
                    value="blue"
                    formControlName="color"
                  />
                  <label class="form-check-label" for="arrayRadio3">Blue</label>
                </div>
  
                <div class="form-check">
                  <input
                    mdbInput
                    class="form-check-input"
                    type="radio"
                    name="color"
                    id="arrayRadio4"
                    value="gray"
                    formControlName="color"
                  />
                  <label class="form-check-label" for="arrayRadio4">Gray</label>
                </div>
              </div>
  
              <div class="col-md-6">
                <span class="fa-lg mb-5">Filter: Sale</span>
  
                <div class="form-check mt-3">
                  <input
                    mdbInput
                    class="form-check-input"
                    type="radio"
                    name="sale"
                    id="arrayRadio5"
                    value="yes"
                    formControlName="sale"
                  />
                  <label class="form-check-label" for="arrayRadio5">Yes</label>
                </div>
  
                <div class="form-check">
                  <input
                    mdbInput
                    class="form-check-input"
                    type="radio"
                    name="sale"
                    id="arrayRadio6"
                    value="no"
                    formControlName="sale"
                  />
                  <label class="form-check-label" for="arrayRadio6">No</label>
                </div>
  
                <button (click)="clearFilters()" type="button" class="btn btn-primary mt-3">
                  Clear all filters
                </button>
              </div>
            </form>
  
            <div class="row text-center">
              <div *ngFor="let item of filteredItems$ | async" class="col-md-4 mt-3" style="max-width: 350px;">
                <div class="card shadow-2">
                  <img [attr.src]="item.img" class="card-img-top" alt="..." />
                  <div class="card-body">
                    <h5 class="card-title">{{ item.product }}</h5>
                    <p class="card-text">{{ item.price }} $</p>
                    <a href="#" class="btn btn-primary ripple-surface">Buy now</a>
                  </div>
                </div>
              </div>
            </div>
          </div>
          
        
    
        
            
          import { Component } from '@angular/core';
          import { FormControl, FormGroup } from '@angular/forms';
          import { Observable } from 'rxjs';
          import { map, startWith } from 'rxjs/operators';
          
          export interface Item {
            id: number;
            color: string;
            price: number;
            sale: string;
            product: string;
            img: string;
            size: number[];
          }
          
          export interface BasicFilters {
            color: string | null;
            sale: string | null;
          }
          
          @Component({
            selector: 'app-root',
            templateUrl: './app.component.html',
            styleUrls: ['./app.component.scss'],
          })
          export class AppComponent {
            items: Item[] = [
              {
                id: 1,
                color: 'black',
                price: 100,
                sale: 'no',
                product: 'Black Jeans Jacket',
                img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/15.webp',
                size: [36, 40, 42],
              },
              {
                id: 2,
                color: 'black',
                price: 100,
                sale: 'no',
                product: 'Black Jeans Jacket',
                img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/15.webp',
                size: [36, 38, 40, 42],
              },
              {
                id: 3,
                color: 'gray',
                price: 80,
                sale: 'yes',
                product: 'Gray Jumper',
                img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/14.webp',
                size: [36, 38, 40],
              },
              {
                id: 4,
                color: 'gray',
                price: 80,
                sale: 'yes',
                product: 'Gray Jumper',
                img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/14.webp',
                size: [40, 42],
              },
              {
                id: 5,
                color: 'red',
                price: 120,
                sale: 'yes',
                product: 'Red Hoodie',
                img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/13.webp',
                size: [36, 40, 42],
              },
              {
                id: 6,
                color: 'blue',
                price: 90,
                sale: 'no',
                product: 'Blue Jeans Jacket',
                img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/12.webp',
                size: [36, 38],
              },
            ];
          
            filteredItems$: Observable<Item[]>;
            filtersGroup: FormGroup;
            
            basicFilters: BasicFilters = {
              color: null,
              sale: null,
            };
            
            constructor() {
              this.filtersGroup = new FormGroup({
                color: new FormControl(),
                sale: new FormControl(),
              });
          
              this.filteredItems$ = this.filtersGroup.valueChanges.pipe(
                startWith(this.basicFilters),
                map((filters: BasicFilters) => {
                  const { color, sale } = filters;
                  let items = this.items;
          
                  if (color) {
                    items = items.filter((item) => item.color === color);
                  }
          
                  if (sale) {
                    items = items.filter((item) => item.sale === sale);
                  }
          
                  return items;
                })
              );
            }
          
            clearFilters() {
              this.filtersGroup.reset();
            }
          }
          
          
        
    

Checkbox example

Note: If there is more than one option, the result of filtering will show items that match both of them.

Filter: Color
Filter: Sale
Black Jeans Jacket
Black Jeans Jacket

100$

Buy now
Gray Jumper
Gray Jumper

100$ 80$

Buy now
Blue Jeans Jacket
Blue Jeans Jacket

90$

Buy now
Red Hoodie
Red Hoodie

150$ 120$

Buy now
Black Jeans Jacket
Black Jeans Jacket

100$

Buy now
Gray Jumper
Gray Jumper

100$ 80$

Buy now
        
            
        <div class="container">
          <form [formGroup]="filtersGroup">
            <div class="col-md-6">
              <span class="fa-lg">Filter: Color</span>

              <div class="form-check mt-3">
                <input
                  mdbInput
                  class="form-check-input"
                  type="checkbox"
                  name="color"
                  id="arrayCheckbox1"
                  value="black"
                  formControlName="black"
                />
                <label class="form-check-label" for="arrayCheckbox1">Black</label>
              </div>

              <div class="form-check">
                <input
                  mdbInput
                  class="form-check-input"
                  type="checkbox"
                  name="color"
                  id="arrayCheckbox2"
                  value="red"
                  formControlName="red"
                />
                <label class="form-check-label" for="arrayCheckbox2">Red</label>
              </div>

              <div class="form-check">
                <input
                  mdbInput
                  class="form-check-input"
                  type="checkbox"
                  name="color"
                  id="arrayCheckbox3"
                  value="blue"
                  formControlName="blue"
                />
                <label class="form-check-label" for="arrayCheckbox3">Blue</label>
              </div>

              <div class="form-check">
                <input
                  mdbInput
                  class="form-check-input"
                  type="checkbox"
                  name="color"
                  id="arrayCheckbox4"
                  value="gray"
                  formControlName="gray"
                />
                <label class="form-check-label" for="arrayCheckbox4">Gray</label>
              </div>
            </div>

            <div class="col-md-6">
              <span class="fa-lg mb-5">Filter: Sale</span>

              <div class="form-check mt-3">
                <input
                  mdbInput
                  class="form-check-input"
                  type="checkbox"
                  name="sale"
                  id="arrayCheckbox5"
                  value="yes"
                  formControlName="saleYes"
                />
                <label class="form-check-label" for="arrayCheckbox5">Yes</label>
              </div>

              <div class="form-check">
                <input
                  mdbInput
                  class="form-check-input"
                  type="checkbox"
                  name="sale"
                  id="arrayCheckbox6"
                  value="no"
                  formControlName="saleNo"
                />
                <label class="form-check-label" for="arrayCheckbox6">No</label>
              </div>

              <button (click)="clearFilters()" type="button" class="btn btn-primary mt-3">
                Clear all filters
              </button>
            </div>
          </form>

          <div class="row text-center">
            <div *ngFor="let item of filteredItems$ | async" class="col-md-4 mt-3"  style="max-width: 350px;">
              <div class="card shadow-2">
                <img [attr.src]="item.img" class="card-img-top" alt="..." />
                <div class="card-body">
                  <h5 class="card-title">{{ item.product }}</h5>
                  <p class="card-text">{{ item.price }} $</p>
                  <a href="#" class="btn btn-primary ripple-surface">Buy now</a>
                </div>
              </div>
            </div>
          </div>
        </div>
        
        
    
        
            
        import { Component } from '@angular/core';
        import { FormControl, FormGroup } from '@angular/forms';
        import { Observable } from 'rxjs';
        import { map, startWith } from 'rxjs/operators';
        
        export interface Item {
          id: number;
          color: string;
          price: number;
          sale: string;
          product: string;
          img: string;
          size: number[];
        }
        export interface Filters {
          [key: string]: string | null;
          black: string | null;
          red: string | null;
          blue: string | null;
          gray: string | null;
          saleYes: string | null;
          saleNo: string | null;
        }
        
        
        @Component({
          selector: 'app-root',
          templateUrl: './app.component.html',
          styleUrls: ['./app.component.scss'],
        })
        export class AppComponent {
          items: Item[] = [
            {
              id: 1,
              color: 'black',
              price: 100,
              sale: 'no',
              product: 'Black Jeans Jacket',
              img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/15.webp',
              size: [36, 40, 42],
            },
            {
              id: 2,
              color: 'black',
              price: 100,
              sale: 'no',
              product: 'Black Jeans Jacket',
              img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/15.webp',
              size: [36, 38, 40, 42],
            },
            {
              id: 3,
              color: 'gray',
              price: 80,
              sale: 'yes',
              product: 'Gray Jumper',
              img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/14.webp',
              size: [36, 38, 40],
            },
            {
              id: 4,
              color: 'gray',
              price: 80,
              sale: 'yes',
              product: 'Gray Jumper',
              img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/14.webp',
              size: [40, 42],
            },
            {
              id: 5,
              color: 'red',
              price: 120,
              sale: 'yes',
              product: 'Red Hoodie',
              img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/13.webp',
              size: [36, 40, 42],
            },
            {
              id: 6,
              color: 'blue',
              price: 90,
              sale: 'no',
              product: 'Blue Jeans Jacket',
              img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/12.webp',
              size: [36, 38],
            },
          ];
        
          filteredItems$: Observable<Item[]>;
          filtersGroup: FormGroup;
          
          defaultFilters: Filters = {
            black: null,
            red: null,
            blue: null,
            gray: null,
            saleYes: null,
            saleNo: null,
          };
        
          constructor() {
            this.filtersGroup = new FormGroup({
              black: new FormControl(),
              red: new FormControl(),
              blue: new FormControl(),
              gray: new FormControl(),
              saleYes: new FormControl(),
              saleNo: new FormControl(),
            });
        
            this.filteredItems$ = this.filtersGroup.valueChanges.pipe(
              startWith(this.defaultFilters),
              map((controls: Filters) => {
                let items = this.items;
                const colors = Object.keys(controls).filter(
                  (control) => controls[control] && !control.startsWith('sale')
                );
        
                const sales = Object.keys(controls)
                  .filter((control) => controls[control] && control.startsWith('sale'))
                  .map((string) => string.toLowerCase().replace('sale', ''));
        
                if (colors.length > 0) {
                  items = items.filter((item) => colors.some((color) => item.color === color));
                }
        
                if (sales.length > 0) {
                  items = items.filter((item) => sales.some((sale) => item.sale === sale));
                }
                return items;
              })
            );
        
          }
        
          clearFilters() {
            this.filtersGroup.reset();
          }
        }
        
        
    

Size example

Note: If there is more than one option, the result of filtering will show items that match both of them.

Filter: Size
Filter: Sale
Black Jeans Jacket
Black Jeans Jacket

100$

Buy now
Gray Jumper
Gray Jumper

100$ 80$

Buy now
Blue Jeans Jacket
Blue Jeans Jacket

90$

Buy now
Red Hoodie
Red Hoodie

150$ 120$

Buy now
Black Jeans Jacket
Black Jeans Jacket

100$

Buy now
Gray Jumper
Gray Jumper

100$ 80$

Buy now
        
            
        <div class="container">
          <form [formGroup]="filtersGroup">
            <div class="col-md-6">
              <span class="fa-lg">Filter: Size</span>
              <div class="form-check mt-3">
                <input
                  mdbInput
                  class="form-check-input"
                  type="checkbox"
                  name="size"
                  id="arrayCheckboxSize1"
                  value="36"
                  formControlName="36"
                />
                <label class="form-check-label" for="arrayCheckboxSize1">36</label>
              </div>

              <div class="form-check">
                <input
                  mdbInput
                  class="form-check-input"
                  type="checkbox"
                  name="size"
                  id="arrayCheckboxSize2"
                  value="38"
                  formControlName="38"
                />
                <label class="form-check-label" for="arrayCheckboxSize2">38</label>
              </div>

              <div class="form-check">
                <input
                  mdbInput
                  class="form-check-input"
                  type="checkbox"
                  name="size"
                  id="arrayCheckboxSize3"
                  value="40"
                  formControlName="40"
                />
                <label class="form-check-label" for="arrayCheckboxSize3">40</label>
              </div>

              <div class="form-check">
                <input
                  mdbInput
                  class="form-check-input"
                  type="checkbox"
                  name="size"
                  id="arrayCheckboxSize4"
                  value="42"
                  formControlName="42"
                />
                <label class="form-check-label" for="arrayCheckboxSize4">42</label>
              </div>
            </div>

            <div class="col-md-6">
              <span class="fa-lg mb-5">Filter: Sale</span>

              <div class="form-check mt-3">
                <input
                  mdbInput
                  class="form-check-input"
                  type="radio"
                  name="sale"
                  id="arrayCheckboxSize5"
                  value="yes"
                  formControlName="sale"
                />
                <label class="form-check-label" for="arrayCheckboxSize5">Yes</label>
              </div>

              <div class="form-check">
                <input
                  mdbInput
                  class="form-check-input"
                  type="radio"
                  name="sale"
                  id="arrayCheckboxSize6"
                  value="no"
                  formControlName="sale"
                />
                <label class="form-check-label" for="arrayCheckboxSize6">No</label>
              </div>

              <button (click)="clearFilters()" type="button" class="btn btn-primary mt-3">
                Clear all filters
              </button>
            </div>
          </form>

          <div class="row text-center">
            <div *ngFor="let item of filteredItems$ | async" class="col-md-4 mt-3"  style="max-width: 350px;">
              <div class="card shadow-2">
                <img [attr.src]="item.img" class="card-img-top" alt="..." />
                <div class="card-body">
                  <h5 class="card-title">{{ item.product }}</h5>
                  <p class="card-text">{{ item.price }} $</p>
                  <a href="#" class="btn btn-primary ripple-surface">Buy now</a>
                </div>
              </div>
            </div>
          </div>
        </div>
        
        
    
        
            
        import { Component } from '@angular/core';
        import { FormControl, FormGroup } from '@angular/forms';
        import { Observable } from 'rxjs';
        import { map, startWith } from 'rxjs/operators';
        
        export interface Item {
          id: number;
          color: string;
          price: number;
          sale: string;
          product: string;
          img: string;
          size: number[];
        }
        export interface Filters {
          [key: string]: string | number | null;
          36: number | null;
          38: number | null;
          40: number | null;
          42: number | null;
          sale: string | null;
        }
        
        @Component({
          selector: 'app-root',
          templateUrl: './app.component.html',
          styleUrls: ['./app.component.scss'],
        })
        export class AppComponent {
          items: Item[] = [
            {
              id: 1,
              color: 'black',
              price: 100,
              sale: 'no',
              product: 'Black Jeans Jacket',
              img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/15.webp',
              size: [36, 40, 42],
            },
            {
              id: 2,
              color: 'black',
              price: 100,
              sale: 'no',
              product: 'Black Jeans Jacket',
              img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/15.webp',
              size: [36, 38, 40, 42],
            },
            {
              id: 3,
              color: 'gray',
              price: 80,
              sale: 'yes',
              product: 'Gray Jumper',
              img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/14.webp',
              size: [36, 38, 40],
            },
            {
              id: 4,
              color: 'gray',
              price: 80,
              sale: 'yes',
              product: 'Gray Jumper',
              img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/14.webp',
              size: [40, 42],
            },
            {
              id: 5,
              color: 'red',
              price: 120,
              sale: 'yes',
              product: 'Red Hoodie',
              img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/13.webp',
              size: [36, 40, 42],
            },
            {
              id: 6,
              color: 'blue',
              price: 90,
              sale: 'no',
              product: 'Blue Jeans Jacket',
              img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/12.webp',
              size: [36, 38],
            },
          ];
        
          filteredItems$: Observable<Item[]>;
          filtersGroup: FormGroup;
        
        
          defaultFilters: Filters = {
            36: null,
            38: null,
            40: null,
            42: null,
            sale: null,
          };
        
        
          constructor() {
            this.filtersGroup = new FormGroup({
              36: new FormControl(),
              38: new FormControl(),
              40: new FormControl(),
              42: new FormControl(),
              sale: new FormControl(),
            });
        
            this.filteredItems$ = this.filtersGroup.valueChanges.pipe(
              startWith(this.defaultFilters),
              map((controls: Filters) => {
                let items = this.items;
                const sizes = Object.keys(controls)
                  .filter((control) => controls[control] && !control.startsWith('sale'))
                  .map((size) => Number(size));
        
                const sale = controls.sale;
        
                if (sizes.length > 0) {
                  items = items.filter((item) =>
                    sizes.some((checkboxSize) => item['size'].some((itemSize) => itemSize === checkboxSize))
                  );
                }
        
                if (sale) {
                  items = items.filter((item) => item.sale === sale);
                }
                return items;
              })
            );
          }
        
          clearFilters() {
            this.filtersGroup.reset();
          }
        }
        
        
    

Spinner & Asynchronous Data example

Price:

        
            
          <h2 class="mb-4">Async example</h2>
          <section class="border p-4 d-flex flex-column justify-content-center align-items-center mb-4">
            <p class="text-center fa-lg fw-bold">Price:</p>
      
            <form [formGroup]="filtersGroup">
              <div class="col-md-6 mt-3 d-flex justify-content-between text-center">
                <mdb-form-control>
                  <input
                    mdbInput
                    type="number"
                    id="min"
                    name="min"
                    class="form-control"
                    formControlName="min"
                  />
                  <label mdbLabel class="form-label" for="min">Min</label>
                </mdb-form-control>
      
                <mdb-form-control>
                  <input
                    mdbInput
                    type="number"
                    id="max"
                    name="max"
                    class="form-control"
                    formControlName="max"
                  />
                  <label mdbLabel class="form-label" for="max">Max</label>
                </mdb-form-control>
              </div>
            </form>
            <div *ngIf="loading" style="height: 300px; width: 100%; z-index: 1029" #container>
              <mdb-loading [backdrop]="false" [show]="true" [container]="container">
                <div class="loading-spinner">
                  <div class="spinner-grow loading-icon" role="status"></div>
                </div>
              </mdb-loading>
            </div>
            <div class="row text-center">
              <div *ngFor="let item of filteredItems$ | async" class="col-md-4 mt-3"  style="max-width: 350px;">
                <div *ngIf="!loading" class="card shadow-2">
                  <img [attr.src]="item.image" class="card-img-top" alt="..." />
      
                  <div class="card-body">
                    <h5 class="card-title">{{ item.product }}</h5>
                    <p class="card-text">$ {{ item.price }}</p>
                    <a href="#" class="btn btn-primary ripple-surface">Buy now</a>
                  </div>
                </div>
              </div>
      
              <!--Section: Docs content-->
            </div>
          
        
    
        
            
          import { HttpClient } from '@angular/common/http';
          import { Component } from '@angular/core';
          import { FormControl, FormGroup } from '@angular/forms';
          import { Observable } from 'rxjs';
          import { delay, map, startWith, switchMap } from 'rxjs/operators';
          
          export interface Item {
            id: number;
            color: string;
            price: number;
            sale: string;
            product: string;
            image: string;
            size: number[];
          }
          
          export interface Filters {
            min: number | null;
            max: number | null;
          }
          
          @Component({
            selector: 'app-root',
            templateUrl: './app.component.html',
            styleUrls: ['./app.component.scss'],
          })
          export class AppComponent {
            loading = true;
          
            filteredItems$: Observable<Item[]>;
            filtersGroup: FormGroup;
          
            defaultFilters: Filters = {
              min: null,
              max: null,
            };
          
            constructor(private http: HttpClient) {
              this.filtersGroup = new FormGroup({
                min: new FormControl(),
                max: new FormControl(),
              });
          
              this.filteredItems$ = this.filtersGroup.valueChanges.pipe(
                startWith(this.defaultFilters),
                switchMap((filters: Filters) => {
                  this.loading = true;
                  return http.get<Item[]>('/assets/products.json').pipe(
                    delay(600),
                    map((data: Item[]) => {
                      const { min, max } = filters;
                      let items: Item[] = data;
                      this.loading = false;
                      if (min && max) {
                        items = data.filter((item) => item['price'] >= min && item['price'] <= max);
                        return items;
                      }
                      if (min) {
                        items = data.filter((item) => item['price'] >= min);
                        return items;
                      }
                      if (max) {
                        items = data.filter((item) => item['price'] <= max);
                        return items;
                      }
          
                      return items;
                    })
                  );
                })
              );
            }
          
            clearFilters() {
              this.filtersGroup.reset();
            }
          }
          
        
    
        
            
          [
          {
            "id": 1,
            "category": "shirts",
            "name": "Fantasy T-shirt",
            "rating": 4,
            "image": "https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/12.webp",
            "description": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.",
            "available": true,
            "size": ["34", "36", "40"],
            "condition": "new",
            "color": "blue",
            "price": 12.99,
            "keywords": ["t-shirt", "sweatshitrt"],
            "discount": 0,
            "gender": "male"
          },
          {
            "id": 2,
            "category": "shirts",
            "name": "Fantasy T-shirt",
            "rating": 5,
            "image": "https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/13.webp",
            "description": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.",
            "available": true,
            "size": ["34", "36", "40", "44"],
            "condition": "new",
            "color": "red",
            "price": 12.99,
            "discount": 0,
            "gender": "male"
          },
          {
            "id": 3,
            "category": "shirts",
            "name": "Fantasy T-shirt",
            "rating": 3,
            "image": "https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/14.webp",
            "description": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.",
            "available": true,
            "size": ["34", "36"],
            "condition": "new",
            "color": "grey",
            "price": 40.99,
            "discount": 10,
            "gender": "male"
          },
          {
            "id": 4,
            "category": "jackets",
            "name": "Denim Jacket",
            "rating": 5,
            "image": "https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/15.webp",
            "description": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.",
            "available": true,
            "condition": "new",
            "color": "grey",
            "price": 40.99,
            "discount": 0,
            "gender": "unisex"
          },
          {
            "id": 5,
            "category": "jeans",
            "name": "Ripped jeans",
            "rating": 5,
            "image": "https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/11.webp",
            "description": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.",
            "available": true,
            "size": ["34", "36", "38", "40"],
            "condition": "renewed",
            "color": "blue",
            "price": 20.99,
            "discount": 5,
            "gender": "female"
          },
          {
            "id": 6,
            "category": "jeans",
            "name": "Boyfriend jeans",
            "rating": 4,
            "image": "https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/10.webp",
            "description": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.",
            "available": false,
            "size": ["34", "36", "38", "40"],
            "condition": "used",
            "color": "blue",
            "price": 20.99,
            "discount": 5,
            "gender": "female"
          },
          {
            "id": 7,
            "category": "shirts",
            "name": "Ripped sweatshirt",
            "rating": 4,
            "image": "https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/7.webp",
            "description": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.",
            "available": true,
            "size": ["34", "36", "38", "40"],
            "condition": "collectible",
            "color": "white",
            "price": 29.99,
            "discount": 5,
            "gender": "female"
          },
          {
            "id": 8,
            "category": "shirts",
            "name": "Longsleeve",
            "rating": 4,
            "image": "https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/8.webp",
            "description": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.",
            "available": true,
            "size": ["40"],
            "condition": "collectible",
            "color": "black",
            "price": 120.99,
            "discount": 0,
            "gender": "male"
          },
          {
            "id": 8,
            "category": "shirts",
            "name": "Stripped sweatshirt",
            "rating": 4,
            "image": "https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/6.webp",
            "description": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.",
            "available": true,
            "size": ["40", "38", "36"],
            "condition": "new",
            "color": "white",
            "price": 32.99,
            "discount": 10,
            "gender": "female"
          },
          {
            "id": 9,
            "category": "trousers",
            "name": "Red chinos",
            "rating": 5,
            "image": "https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/5.webp",
            "description": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.",
            "available": true,
            "size": ["40", "38", "36"],
            "condition": "new",
            "color": "red",
            "price": 62.99,
            "discount": 10,
            "gender": "female"
          },
          {
            "id": 10,
            "category": "coats",
            "name": "Camel coat",
            "rating": 5,
            "image": "https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/4.webp",
            "description": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.",
            "available": true,
            "size": ["40", "38", "36"],
            "condition": "used",
            "color": "brown",
            "price": 62.99,
            "discount": 10,
            "gender": "female"
          },
          {
            "id": 11,
            "category": "jeans",
            "name": "Blue jeans",
            "rating": 5,
            "image": "https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/3.webp",
            "description": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.",
            "available": true,
            "size": ["40", "38", "36"],
            "condition": "new",
            "color": "blue",
            "price": 42.99,
            "discount": 0,
            "gender": "female"
          },
          {
            "id": 12,
            "category": "shirts",
            "name": "Orange T-shirt",
            "rating": 3,
            "image": "https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/3.webp",
            "description": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.",
            "available": true,
            "size": ["40", "38", "36"],
            "condition": "new",
            "color": "orange",
            "price": 12.99,
            "discount": 0,
            "gender": "female"
          },
          {
            "id": 13,
            "category": "skirts",
            "name": "Ballerina skirt",
            "rating": 4,
            "image": "https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/2.webp",
            "description": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.",
            "available": true,
            "size": ["38", "36"],
            "condition": "collectible",
            "color": "white",
            "price": 12.99,
            "discount": 0,
            "gender": "female"
          }
            ]
          
        
    

Animations

The full list of available animations you can find here.

Filter: Color
Filter: Sale
        
            
        <div class="container">
          <form [formGroup]="filtersGroup">
            <div class="col-md-6">
              <span class="fa-lg">Filter: Color</span>

              <div class="form-check mt-3">
                <input
                  mdbInput
                  class="form-check-input"
                  type="radio"
                  name="color"
                  id="arrayRadio10"
                  value="black"
                  formControlName="color"
                />
                <label class="form-check-label" for="arrayRadio10">Black</label>
              </div>

              <div class="form-check">
                <input
                  mdbInput
                  class="form-check-input"
                  type="radio"
                  name="color"
                  id="arrayRadio20"
                  value="red"
                  formControlName="color"
                />
                <label class="form-check-label" for="arrayRadio20">Red</label>
              </div>

              <div class="form-check">
                <input
                  mdbInput
                  class="form-check-input"
                  type="radio"
                  name="color"
                  id="arrayRadio30"
                  value="blue"
                  formControlName="color"
                />
                <label class="form-check-label" for="arrayRadio30">Blue</label>
              </div>

              <div class="form-check">
                <input
                  mdbInput
                  class="form-check-input"
                  type="radio"
                  name="color"
                  id="arrayRadio40"
                  value="gray"
                  formControlName="color"
                />
                <label class="form-check-label" for="arrayRadio40">Gray</label>
              </div>
            </div>

            <div class="col-md-6">
              <span class="fa-lg mb-5">Filter: Sale</span>

              <div class="form-check mt-3">
                <input
                  mdbInput
                  class="form-check-input"
                  type="radio"
                  name="sale"
                  id="arrayRadio50"
                  value="yes"
                  formControlName="sale"
                />
                <label class="form-check-label" for="arrayRadio50">Yes</label>
              </div>

              <div class="form-check">
                <input
                  mdbInput
                  class="form-check-input"
                  type="radio"
                  name="sale"
                  id="arrayRadio60"
                  value="no"
                  formControlName="sale"
                />
                <label class="form-check-label" for="arrayRadio60">No</label>
              </div>

              <button (click)="clearFilters()" type="button" class="btn btn-primary mt-3">
                Clear all filters
              </button>
            </div>
          </form>

          <div class="row text-center">
            <div *ngFor="let item of filteredItems$ | async" class="col-md-4 mt-3"  style="max-width: 350px;">
              <div
                class="card shadow-2"
                [@zoomIn]="animationState"
                (@zoomIn.done)="onAnimationDone()"
              >
                <img [attr.src]="item.img" class="card-img-top" alt="..." />
                <div class="card-body">
                  <h5 class="card-title">{{ item.product }}</h5>
                  <p class="card-text">{{ item.price }} $</p>
                  <a href="#" class="btn btn-primary ripple-surface">Buy now</a>
                </div>
              </div>
            </div>
          </div>
        </div>
        
        
    
        
            
        import { Component } from '@angular/core';
        import { FormControl, FormGroup } from '@angular/forms';
        import { Observable } from 'rxjs';
        import { map, startWith, tap } from 'rxjs/operators';
        import { zoomInAnimation } from 'mdb-angular-ui-kit/animations';
        
        export interface Item {
          id: number;
          color: string;
          price: number;
          sale: string;
          product: string;
          img: string;
          size: number[];
        }
        
        export interface Filters {
          color: string | null;
          sale: string | null;
        }
        
        @Component({
          selector: 'app-root',
          templateUrl: './app.component.html',
          styleUrls: ['./app.component.scss'],
          animations: [zoomInAnimation()],
        })
        export class AppComponent {
          animationState = false;
        
          items: Item[] = [
            {
              id: 1,
              color: 'black',
              price: 100,
              sale: 'no',
              product: 'Black Jeans Jacket',
              img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/15.webp',
              size: [36, 40, 42],
            },
            {
              id: 2,
              color: 'black',
              price: 100,
              sale: 'no',
              product: 'Black Jeans Jacket',
              img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/15.webp',
              size: [36, 38, 40, 42],
            },
            {
              id: 3,
              color: 'gray',
              price: 80,
              sale: 'yes',
              product: 'Gray Jumper',
              img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/14.webp',
              size: [36, 38, 40],
            },
            {
              id: 4,
              color: 'gray',
              price: 80,
              sale: 'yes',
              product: 'Gray Jumper',
              img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/14.webp',
              size: [40, 42],
            },
            {
              id: 5,
              color: 'red',
              price: 120,
              sale: 'yes',
              product: 'Red Hoodie',
              img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/13.webp',
              size: [36, 40, 42],
            },
            {
              id: 6,
              color: 'blue',
              price: 90,
              sale: 'no',
              product: 'Blue Jeans Jacket',
              img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/12.webp',
              size: [36, 38],
            },
          ];
        
          filteredItems$: Observable<Item[]>;
          filtersGroup: FormGroup;
          
          defaultFilters: Filters = {
            color: null,
            sale: null,
          };
          constructor() {
            this.filtersGroup = new FormGroup({
              color: new FormControl(),
              sale: new FormControl(),
            });
        
            this.filteredItems$ = this.filtersGroup.valueChanges.pipe(
              startWith(this.defaultFilters),
              map((filters: Filters) => {
                const { color, sale } = filters;
                let items = this.items;
                if (color) {
                  items = items.filter((item) => item.color === color);
                }
        
                if (sale) {
                  items = items.filter((item) => item.sale === sale);
                }
        
                return items;
              }),
              tap(() =>
                setTimeout(() => {
                  this.animationState = !this.animationState;
                }, 0)
              )
            );
          }
        
          clearFilters() {
            this.filtersGroup.reset();
          }
        
          onAnimationDone() {
            this.animationState = false;
          }
        }
        
        
    

Filter and sort

Filter: Color
Filter: Sale
        
            
        <div class="container">
          <form [formGroup]="filtersGroup">
            <div class="col-md-6">
              <span class="fa-lg">Filter: Color</span>

              <div class="form-check mt-3">
                <input
                  mdbInput
                  class="form-check-input"
                  type="radio"
                  name="color"
                  id="arrayRadioSort1"
                  value="black"
                  formControlName="color"
                />
                <label class="form-check-label" for="arrayRadioSort1">Black</label>
              </div>

              <div class="form-check">
                <input
                  mdbInput
                  class="form-check-input"
                  type="radio"
                  name="color"
                  id="arrayRadioSort2"
                  value="red"
                  formControlName="color"
                />
                <label class="form-check-label" for="arrayRadioSort2">Red</label>
              </div>

              <div class="form-check">
                <input
                  mdbInput
                  class="form-check-input"
                  type="radio"
                  name="color"
                  id="arrayRadioSort3"
                  value="blue"
                  formControlName="color"
                />
                <label class="form-check-label" for="arrayRadioSort3">Blue</label>
              </div>

              <div class="form-check">
                <input
                  mdbInput
                  class="form-check-input"
                  type="radio"
                  name="color"
                  id="arrayRadioSort4"
                  value="gray"
                  formControlName="color"
                />
                <label class="form-check-label" for="arrayRadioSort4">Gray</label>
              </div>
            </div>

            <div class="col-md-6 my-3">
              <span class="fa-lg mb-5">Filter: Sale</span>

              <div class="form-check mt-3">
                <input
                  mdbInput
                  class="form-check-input"
                  type="radio"
                  name="sale"
                  id="arrayRadioSort5"
                  value="yes"
                  formControlName="sale"
                />
                <label class="form-check-label" for="arrayRadioSort5">Yes</label>
              </div>

              <div class="form-check">
                <input
                  mdbInput
                  class="form-check-input"
                  type="radio"
                  name="sale"
                  id="arrayRadioSort6"
                  value="no"
                  formControlName="sale"
                />
                <label class="form-check-label" for="arrayRadioSort6">No</label>
              </div>

              <button (click)="clearFilters()" type="button" class="btn btn-primary mt-3">
                Clear all filters
              </button>
            </div>  

            <mdb-form-control>
              <mdb-select formControlName="sorting">
                <mdb-option *ngFor="let option of options" [value]="option.value">{{
                  option.label  
                }}</mdb-option>
              </mdb-select>
              <label mdbLabel class="form-label">Sort</label>
            </mdb-form-control>
          </form>

          <div class="row text-center">
            <div *ngFor="let item of filteredItems$ | async" class="col-md-4 mt-3"  style="max-width: 350px;">
              <div class="card shadow-2">
                <img [attr.src]="item.img" class="card-img-top" alt="..." />
                <div class="card-body">
                  <h5 class="card-title">{{ item.product }}</h5>
                  <p class="card-text">{{ item.price }} $</p>
                  <a href="#" class="btn btn-primary ripple-surface">Buy now</a>
                </div>
              </div>
            </div>
          </div>
        </div>
        
        
    
        
            
        import { Component } from '@angular/core';
        import { FormControl, FormGroup } from '@angular/forms';
        import { Observable } from 'rxjs';
        import { map, startWith, } from 'rxjs/operators';
        
        export interface Item {
          id: number;
          color: string;
          price: number;
          sale: string;
          product: string;
          img: string;
          size: number[];
        }
        export interface Filters {
          color: string | null;
          sale: string | null;
          sorting: string | null;
        }
        
        
        @Component({
          selector: 'app-root',
          templateUrl: './app.component.html',
          styleUrls: ['./app.component.scss'],
        })
        export class AppComponent {
          options = [
            { value: 'productasc', label: 'Product name ascending' },
            { value: 'productdesc', label: 'Product name descending' },
            { value: 'pricedesc', label: 'Highest price' },
            { value: 'priceasc', label: 'Lowest price' },
          ];
        
          items: Item[] = [
            {
              id: 1,
              color: 'black',
              price: 100,
              sale: 'no',
              product: 'Black Jeans Jacket',
              img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/15.webp',
              size: [36, 40, 42],
            },
            {
              id: 2,
              color: 'black',
              price: 100,
              sale: 'no',
              product: 'Black Jeans Jacket',
              img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/15.webp',
              size: [36, 38, 40, 42],
            },
            {
              id: 3,
              color: 'gray',
              price: 80,
              sale: 'yes',
              product: 'Gray Jumper',
              img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/14.webp',
              size: [36, 38, 40],
            },
            {
              id: 4,
              color: 'gray',
              price: 80,
              sale: 'yes',
              product: 'Gray Jumper',
              img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/14.webp',
              size: [40, 42],
            },
            {
              id: 5,
              color: 'red',
              price: 120,
              sale: 'yes',
              product: 'Red Hoodie',
              img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/13.webp',
              size: [36, 40, 42],
            },
            {
              id: 6,
              color: 'blue',
              price: 90,
              sale: 'no',
              product: 'Blue Jeans Jacket',
              img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/12.webp',
              size: [36, 38],
            },
          ];
        
          filteredItems$: Observable<Item[]>;
        
          filtersGroup: FormGroup;
        
          sortDefaultFilters: Filters = {
            color: null,
            sale: null,
            sorting: null,
          };
        
          constructor() {
            this.filtersGroup = new FormGroup({
              color: new FormControl(),
              sale: new FormControl(),
              sorting: new FormControl(),
            });
        
            this.filteredItems$ = this.filtersGroup.valueChanges.pipe(
              startWith(this.sortDefaultFilters),
              map((filters: Filters) => {
                const { color, sale, sorting } = filters;
                let items = this.items;
        
                if (color) {
                  items = items.filter((item) => item.color === color);
                }
        
                if (sale) {
                  items = items.filter((item) => item.sale === sale);
                }
        
                if (sorting && sorting.startsWith('product')) {
                  items = items.sort((a, b) =>
                    sorting.endsWith('asc')
                      ? a['product'].localeCompare(b['product'])
                      : -1 * a['product'].localeCompare(b['product'])
                  );
                }
        
                if (sorting && sorting.startsWith('price')) {
                  items = items.sort((a, b) =>
                    sorting.endsWith('asc') ? a['price'] - b['price'] : b['price'] - a['price']
                  );
                }
                return items;
              })
            );
          }
        
          clearFilters() {
            this.filtersGroup.reset();
          }
        }
        
        
    

Range example

Price:

Current: 80$

Current: 120$

Black Jeans Jacket
Black Jeans Jacket

100$

Buy now
Gray Jumper
Gray Jumper

100$ 80$

Buy now
Blue Jeans Jacket
Blue Jeans Jacket

90$

Buy now
Red Hoodie
Red Hoodie

150$ 120$

Buy now
Black Jeans Jacket
Black Jeans Jacket

100$

Buy now
Gray Jumper
Gray Jumper

100$ 80$

Buy now
        
            
      <div class="container">
        <form [formGroup]="filtersGroup">
          <div class="col-md-6">
            <mdb-range formControlName="min" [min]="80" [max]="120"></mdb-range>
            Current min ${{ rangeMin }}
            <mdb-range formControlName="max" [min]="80" [max]="120"></mdb-range>
            Current max ${{ rangeMax }}
          </div>
        </form>
      
        <div class="row text-center">
          <div *ngFor="let item of filteredItems$ | async" class="col-md-4 mt-3">
            <div class="card shadow-2">
              <img [attr.src]="item.img" class="card-img-top" alt="..." />
              <div class="card-body">
                <h5 class="card-title">{{ item.product }}</h5>
                <p class="card-text">{{ item.price }} $</p>
                <a href="#" class="btn btn-primary ripple-surface">Buy now</a>
              </div>
            </div>
          </div>
        </div>
      </div>
      
        
    
        
            
      import { Component } from '@angular/core';
      import { FormControl, FormGroup } from '@angular/forms';
      import { Observable } from 'rxjs';
      import { map, startWith } from 'rxjs/operators';
      
      export interface Item {
        id: number;
        color: string;
        price: number;
        sale: string;
        product: string;
        img: string;
        size: number[];
      }
      
      export interface Filters {
        min: number;
        max: number;
      }
      
      
      @Component({
        selector: 'app-root',
        templateUrl: './app.component.html',
        styleUrls: ['./app.component.scss'],
      })
      export class AppComponent {
        items: Item[] = [
          {
            id: 1,
            color: 'black',
            price: 100,
            sale: 'no',
            product: 'Black Jeans Jacket',
            img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/15.webp',
            size: [36, 40, 42],
          },
          {
            id: 2,
            color: 'black',
            price: 100,
            sale: 'no',
            product: 'Black Jeans Jacket',
            img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/15.webp',
            size: [36, 38, 40, 42],
          },
          {
            id: 3,
            color: 'gray',
            price: 80,
            sale: 'yes',
            product: 'Gray Jumper',
            img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/14.webp',
            size: [36, 38, 40],
          },
          {
            id: 4,
            color: 'gray',
            price: 80,
            sale: 'yes',
            product: 'Gray Jumper',
            img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/14.webp',
            size: [40, 42],
          },
          {
            id: 5,
            color: 'red',
            price: 120,
            sale: 'yes',
            product: 'Red Hoodie',
            img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/13.webp',
            size: [36, 40, 42],
          },
          {
            id: 6,
            color: 'blue',
            price: 90,
            sale: 'no',
            product: 'Blue Jeans Jacket',
            img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/12.webp',
            size: [36, 38],
          },
        ];
      
        filteredItems$: Observable<Item[]>;
        filtersGroup: FormGroup;
      
        rangeMin = 80;
        rangeMax = 120;
      
        defaultFilters: Filters = {
          min: 80,
          max: 120,
        };
      
      
        constructor() {
          this.filtersGroup = new FormGroup({
            min: new FormControl(80),
            max: new FormControl(120),
          });
      
          this.filteredItems$ = this.filtersGroup.valueChanges.pipe(
            startWith({min: 80, max: 120}),
            map((filters: Filters) => {
              const { min, max } = filters;
              let items = this.items;
              this.rangeMin = min;
              this.rangeMax = max;
              if (min && max) {
                items = items.filter((item) => item['price'] >= min && item['price'] <= max);
                return items;
              }
      
              if (min) {
                items = items.filter((item) => item['price'] >= min);
                return items;
              }
      
              if (max) {
                items = items.filter((item) => item['price'] <= max);
                return items;
              }
      
              return items;
            })
          );
        }
      
        clearFilters() {
          this.filtersGroup.reset();
        }
      }
      
        
    

Buttons example

        
            
      <div class="container">
        <form [formGroup]="filtersGroup">
          <div class="col-md-6">
            <div class="form-check mt-3">
              <button
                type="button"
                class="btn btn-primary"
                (click)="filtersGroup.get('sort')?.setValue('asc')"
              >
                Sort by product name ascending
              </button>
            </div>

            <div class="form-check">
              <button
                type="button"
                class="btn btn-primary"
                (click)="filtersGroup.get('sort')?.setValue('desc')"
              >
                Sort by product name descending
              </button>
            </div>
          </div>
        </form>

        <div class="row text-center">
          <div *ngFor="let item of filteredItems$ | async" class="col-md-4 mt-3"  style="max-width: 350px;">
            <div class="card shadow-2">
              <img [attr.src]="item.img" class="card-img-top" alt="..." />
              <div class="card-body">
                <h5 class="card-title">{{ item.product }}</h5>
                <p class="card-text">{{ item.price }} $</p>
                <a href="#" class="btn btn-primary ripple-surface">Buy now</a>
              </div>
            </div>
          </div>
        </div>
      </div>
      
        
    
        
            
      import { Component } from '@angular/core';
      import { FormControl, FormGroup } from '@angular/forms';
      import { Observable } from 'rxjs';
      import { map, startWith } from 'rxjs/operators';
      
      export interface Item {
        id: number;
        color: string;
        price: number;
        sale: string;
        product: string;
        img: string;
        size: number[];
      }
      
      export interface Filters {
        sort: string | null;
      }
      
      @Component({
        selector: 'app-root',
        templateUrl: './app.component.html',
        styleUrls: ['./app.component.scss'],
      })
      export class AppComponent {
        items: Item[] = [
          {
            id: 1,
            color: 'black',
            price: 100,
            sale: 'no',
            product: 'Black Jeans Jacket',
            img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/15.webp',
            size: [36, 40, 42],
          },
          {
            id: 2,
            color: 'black',
            price: 100,
            sale: 'no',
            product: 'Black Jeans Jacket',
            img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/15.webp',
            size: [36, 38, 40, 42],
          },
          {
            id: 3,
            color: 'gray',
            price: 80,
            sale: 'yes',
            product: 'Gray Jumper',
            img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/14.webp',
            size: [36, 38, 40],
          },
          {
            id: 4,
            color: 'gray',
            price: 80,
            sale: 'yes',
            product: 'Gray Jumper',
            img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/14.webp',
            size: [40, 42],
          },
          {
            id: 5,
            color: 'red',
            price: 120,
            sale: 'yes',
            product: 'Red Hoodie',
            img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/13.webp',
            size: [36, 40, 42],
          },
          {
            id: 6,
            color: 'blue',
            price: 90,
            sale: 'no',
            product: 'Blue Jeans Jacket',
            img: 'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/12.webp',
            size: [36, 38],
          },
        ];
      
        filteredItems$: Observable<Item[]>;
        filtersGroup: FormGroup;
      
        basicButtonFilters: Filters = {
          sort: null,
        };
      
        constructor() {
          this.filtersGroup = new FormGroup({
            sort: new FormControl(),
          });
      
          this.filteredItems$ = this.filtersGroup.valueChanges.pipe(
            startWith(this.basicButtonFilters),
            map((filters: Filters) => {
              const { sort } = filters;
              let items = this.items;
      
              if (sort) {
                items = items.sort((a, b) =>
                  sort === 'asc'
                    ? a['product'].localeCompare(b['product'])
                    : -1 * a['product'].localeCompare(b['product'])
                );
              }
      
              return items;
            })
          );
        }
      
        clearFilters() {
          this.filtersGroup.reset();
        }
      }
      
        
    

Full page example

        
            
      <header>
        <!-- Navbar -->
        <nav class="navbar sticky-top navbar-expand-lg navbar-light bg-white">
          <!-- Container wrapper -->
          <div class="container-fluid">
            <!-- Navbar brand -->
      
            <!-- Toggle button -->
            <button
              class="navbar-toggler"
              type="button"
              (click)="buttonsNav.toggle()"
              aria-expanded="false"
              aria-label="Toggle navigation"
            >
              <i class="fas fa-bars"></i>
            </button>
      
            <!-- Collapsible wrapper -->
            <div
              class="collapse navbar-collapse"
              id="navbarButtonsExample"
              mdbCollapse
              #buttonsNav="mdbCollapse"
            >
              <!-- Left links -->
              <ul class="navbar-nav me-auto mb-2 mb-lg-0">
                <a class="navbar-brand" href="https://mdbecommerce.com/">
                  <i class="fab fa-mdb fa-2x" alt="mdb logo"></i>
                </a>
              </ul>
              <!-- Right links -->
      
              <ul class="navbar-nav ml-auto">
                <li class="nav-item my-auto">
                  <a class="nav-link active" aria-current="page" href="#"
                    ><span class="badge rounded-pill bg-danger">1</span
                    ><i class="fas fa-shopping-cart"></i
                  ></a>
                </li>
                <!-- Navbar dropdown -->
                <div mdbDropdown class="dropdown my-auto">
                  <a
                    class="dropdown-toggle text-black"
                    role="button"
                    id="dropdownMenuLink"
                    mdbDropdownToggle
                    aria-expanded="false"
                  >
                    <i class="united kingdom flag m-0"></i>
                  </a>
                  <ul
                    mdbDropdownMenu
                    class="dropdown-menu"
                    aria-labelledby="dropdownMenuLink"
                  >
                    <li><a class="dropdown-item" href="#">Action</a></li>
                    <li><a class="dropdown-item" href="#">Another action</a></li>
                    <li><a class="dropdown-item" href="#">Something else here</a></li>
                  </ul>
                </div>
      
                <li class="nav-item my-auto">
                  <a class="nav-link active" aria-current="page" href="#">Shop</a>
                </li>
                <li class="nav-item my-auto">
                  <a class="nav-link active" aria-current="page" href="#">Contact</a>
                </li>
                <li class="nav-item my-auto">
                  <a class="nav-link active" aria-current="page" href="#">Sign in</a>
                </li>
                <li class="nav-item">
                  <a class="nav-link" href="#"
                    ><button
                      type="button"
                      class="btn btn-outline-dark btn-rounded ripple-surface ripple-surface-dark"
                      data-ripple-color="dark"
                    >
                      Sign up
                    </button></a
                  >
                </li>
              </ul>
            </div>
            <!-- Collapsible wrapper -->
          </div>
          <!-- Container wrapper -->
        </nav>
        <!-- Navbar -->
        <div
          class="p-5 text-center bg-image"
          style="
            background-image: url('https://mdbootstrap.com/img/Photos/Others/clothes(5)-crop.jpg');
            height: 400px;
          "
        >
          <div class="mask" style="background-color: rgba(0, 0, 0, 0.7)">
            <div class="d-flex justify-content-center align-items-center h-100">
              <div class="text-white">
                <h1 class="mb-3">Shop</h1>
              </div>
            </div>
          </div>
        </div>
      </header>
      <main>
        <div class="container mt-5" [formGroup]="filtersGroup">
          <div class="row">
            <div class="col-md-4">
              <!-- Section: Sidebar -->
              <section>
                <!-- Section: Filters -->
                <section id="filters" data-auto-filter="true">
                  <h5>Filters</h5>
      
                  <!-- Section: Condition -->
                  <section class="mb-4">
                    <h6 class="font-weight-bold mb-3">Condition</h6>
      
                    <div class="form-check mb-3">
                      <input
                        mdbCheckbox
                        class="form-check-input"
                        type="checkbox"
                        value="new"
                        id="checkbox1"
                        formControlName="conditionNew"
                      />
                      <label class="form-check-label" for="checkbox1"> NEW </label>
                    </div>
      
                    <div class="form-check mb-3">
                      <input
                        mdbCheckbox
                        class="form-check-input"
                        type="checkbox"
                        value="used"
                        id="checkbox2"
                        formControlName="conditionUsed"
                      />
                      <label class="form-check-label" for="checkbox2"> USED </label>
                    </div>
                    <div class="form-check mb-3">
                      <input
                        mdbCheckbox
                        class="form-check-input"
                        type="checkbox"
                        value="collectible"
                        id="checkbox3"
                        formControlName="conditionCollectible"
                      />
                      <label class="form-check-label" for="checkbox3">
                        COLLECTIBLE
                      </label>
                    </div>
      
                    <div class="form-check mb-3">
                      <input
                        mdbCheckbox
                        class="form-check-input"
                        type="checkbox"
                        value="renewed"
                        id="checkbox4"
                        formControlName="conditionRenewed"
                      />
                      <label class="form-check-label" for="checkbox4">
                        RENEWED
                      </label>
                    </div>
                  </section>
                  <!-- Section: Condition -->
      
                  <!-- Section: Avg. Customer Review -->
                  <section class="mb-4">
                    <h6 class="font-weight-bold mb-3">Avg. Customer Review</h6>
      
                    <mdb-rating
                      (onSelect)="filtersGroup.get('rating')?.setValue($event)"
                      style="cursor: pointer"
                    >
                      <mdb-rating-icon
                        mdbTooltip="1"
                        class="text-primary"
                      ></mdb-rating-icon>
                      <mdb-rating-icon
                        mdbTooltip="2"
                        class="text-primary"
                      ></mdb-rating-icon>
                      <mdb-rating-icon
                        mdbTooltip="3"
                        class="text-primary"
                      ></mdb-rating-icon>
                      <mdb-rating-icon
                        mdbTooltip="4"
                        class="text-primary"
                      ></mdb-rating-icon>
                      <mdb-rating-icon
                        mdbTooltip="5"
                        class="text-primary"
                      ></mdb-rating-icon>
                    </mdb-rating>
                  </section>
                  <!-- Section: Avg. Customer Review -->
      
                  <!-- Section: Price -->
                  <section class="mb-4">
                    <h6 class="font-weight-bold mb-3">Price</h6>
                    <div class="form-check mb-3">
                      <input
                        mdbRadio
                        class="form-check-input"
                        type="radio"
                        name="price"
                        id="radio1"
                        formControlName="price"
                        value="<25"
                      />
                      <label class="form-check-label" for="radio1"> Under $25 </label>
                    </div>
      
                    <div class="form-check mb-3">
                      <input
                        mdbRadio
                        class="form-check-input"
                        type="radio"
                        name="price"
                        id="radio2"
                        formControlName="price"
                        value="25-50"
                      />
                      <label class="form-check-label" for="radio2">
                        $25 to $50
                      </label>
                    </div>
      
                    <div class="form-check mb-3">
                      <input
                        mdbRadio
                        class="form-check-input"
                        type="radio"
                        name="price"
                        id="radio3"
                        formControlName="price"
                        value="50-100"
                      />
                      <label class="form-check-label" for="radio3">
                        $50 to $100
                      </label>
                    </div>
      
                    <div class="form-check mb-3">
                      <input
                        mdbRadio
                        class="form-check-input"
                        type="radio"
                        name="price"
                        id="radio4"
                        formControlName="price"
                        value="100-200"
                      />
                      <label class="form-check-label" for="radio4">
                        $100 to $200
                      </label>
                    </div>
                    <div class="form-check mb-3">
                      <input
                        mdbRadio
                        class="form-check-input"
                        type="radio"
                        name="price"
                        id="radio5"
                        formControlName="price"
                        value=">200"
                      />
                      <label class="form-check-label" for="radio5">
                        $200 & above
                      </label>
                    </div>
                  </section>
                  <!-- Section: Price -->
      
                  <!-- Section: Size -->
                  <section class="mb-4" data-filter="size">
                    <h6 class="font-weight-bold mb-3">Size</h6>
      
                    <div class="form-check mb-3">
                      <input
                        mdbCheckbox
                        class="form-check-input"
                        type="checkbox"
                        value="34"
                        id="checkbox5"
                        formControlName="size34"
                      />
                      <label class="form-check-label" for="checkbox5"> 34 </label>
                    </div>
      
                    <div class="form-check mb-3">
                      <input
                        mdbCheckbox
                        class="form-check-input"
                        type="checkbox"
                        value="36"
                        id="checkbox6"
                        formControlName="size36"
                      />
                      <label class="form-check-label" for="checkbox6"> 36 </label>
                    </div>
                    <div class="form-check mb-3">
                      <input
                        mdbCheckbox
                        class="form-check-input"
                        type="checkbox"
                        value="38"
                        id="checkbox7"
                        formControlName="size38"
                      />
                      <label class="form-check-label" for="checkbox7"> 38 </label>
                    </div>
      
                    <div class="form-check mb-3">
                      <input
                        mdbCheckbox
                        class="form-check-input"
                        type="checkbox"
                        value="40"
                        id="checkbox8"
                        formControlName="size40"
                      />
                      <label class="form-check-label" for="checkbox8"> 40 </label>
                    </div>
                  </section>
                  <!-- Section: Size -->
      
                  <!-- Section: Color -->
                  <section class="mb-4" data-filter="color">
                    <h6 class="font-weight-bold mb-3">Color</h6>
      
                    <div class="form-check form-check-inline mx-0 px-0 py-3">
                      <input
                        formControlName="color"
                        mdbRadio
                        class="btn-check"
                        type="radio"
                        name="color"
                        id="colorRadio1"
                        value="white"
                      />
                      <label
                        class="btn bg-light btn-rounded p-3"
                        for="colorRadio1"
                      ></label>
                    </div>
      
                    <div class="form-check form-check-inline mx-0">
                      <input
                        formControlName="color"
                        mdbRadio
                        class="btn-check"
                        type="radio"
                        name="color"
                        id="colorRadio2"
                        value="grey"
                      />
                      <label
                        class="btn btn-rounded p-3"
                        for="colorRadio2"
                        style="background-color: #bdbdbd"
                      ></label>
                    </div>
      
                    <div class="form-check form-check-inline mx-0">
                      <input
                        formControlName="color"
                        mdbRadio
                        class="btn-check"
                        type="radio"
                        name="color"
                        id="colorRadio3"
                        value="black"
                      />
                      <label
                        class="btn bg-dark text-white btn-rounded p-3"
                        for="colorRadio3"
                      ></label>
                    </div>
      
                    <div class="form-check form-check-inline mx-0">
                      <input
                        formControlName="color"
                        mdbRadio
                        class="btn-check"
                        type="radio"
                        name="color"
                        id="colorRadio5"
                        value="blue"
                      />
                      <label
                        class="btn bg-primary btn-rounded p-3"
                        for="colorRadio5"
                      ></label>
                    </div>
      
                    <div class="form-check form-check-inline mx-0">
                      <input
                        formControlName="color"
                        mdbRadio
                        class="btn-check"
                        type="radio"
                        name="color"
                        id="colorRadio9"
                        value="red"
                      />
                      <label
                        class="btn bg-danger btn-rounded p-3"
                        for="colorRadio9"
                      ></label>
                    </div>
      
                    <div class="form-check form-check-inline mx-0">
                      <input
                        formControlName="color"
                        mdbRadio
                        class="btn-check"
                        type="radio"
                        name="color"
                        id="colorRadio10"
                        value="orange"
                      />
                      <label
                        class="btn bg-warning btn-rounded p-3"
                        for="colorRadio10"
                      ></label>
                    </div>
                  </section>
                  <!-- Section: Color -->
                </section>
                <!-- Section: Filters -->
              </section>
              <!-- Section: Sidebar -->
            </div>
            <div class="col-md-8">
              <div class="row justify-content-center">
                <div class="col-md-6 my-auto py-3">
                  <mdb-form-control>
                    <mdb-select formControlName="sort">
                      <mdb-option
                        *ngFor="let option of options"
                        [value]="option.value"
                        >{{ option.label }}</mdb-option
                      >
                    </mdb-select>
                    <label mdbLabel class="form-label">Sort</label>
                  </mdb-form-control>
                </div>
              </div>
              <div class="row mb-4" id="content" style="display: flex">
                <div class="row text-center">
                  <h3 *ngIf="noItemsFound" class="text-center mt-5">
                    No items found
                  </h3>
                  <div
                    *ngFor="let item of filteredItems$ | async"
                    class="col-md-4 mt-3"
                    style="max-width: 350px"
                  >
                    <div class="card shadow-2">
                      <img [attr.src]="item.image" class="card-img-top" alt="..." />
                      <div class="card-body">
                        <h5 class="card-title">{{ item.name }}</h5>
                        <p class="card-text">{{ item.price }} $</p>
                        <a href="#" class="btn btn-primary ripple-surface">Buy now</a>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </main>
      <footer class="bg-dark text-white text-center text-lg-left">
        <!-- Socials -->
        <div class="bg-primary text-center p-3">
          <div class="row">
            <div class="col-md-6">
              <span class="font-weight-bold"
                >Get connected with us on social networks!</span
              >
            </div>
            <div class="col-md-6">
              <i class="fab fa-instagram"></i>
              <i class="fab fa-linkedin-in ms-4"></i>
              <i class="fab fa-twitter ms-4"></i>
              <i class="fab fa-facebook-f ms-4"></i>
            </div>
          </div>
        </div>
        <!-- Socials -->
      
        <!-- Grid container -->
        <div class="container p-5">
          <!--Grid row-->
          <div class="row p-2">
            <!--Grid column-->
            <div class="col-md-3 mx-auto py-4 text-start">
              <h5 class="text-uppercase">About me</h5>
              <hr class="mb-4 mt-0" />
      
              <p>
                Here you can use rows and columns to organize your footer content.
                Lorem ipsum dolor sit amet, consectetur adipisicing elit.
              </p>
            </div>
            <!--Grid column-->
      
            <!--Grid column-->
            <div class="col-md-3 mx-auto py-4">
              <h5 class="text-uppercase text-start">Products</h5>
              <hr class="mb-4 mt-0" />
      
              <ul class="list-unstyled mb-0 text-start">
                <li class="mb-2">
                  <a href="#!" class="text-white">MDBootstrap</a>
                </li>
                <li class="mb-2">
                  <a href="#!" class="text-white">MDWordPress</a>
                </li>
                <li class="mb-2">
                  <a href="#!" class="text-white">BrandFlow</a>
                </li>
                <li>
                  <a href="#!" class="text-white">Bootstrap Angular</a>
                </li>
              </ul>
            </div>
            <!--Grid column-->
      
            <!--Grid column-->
            <div class="col-md-3 mx-auto py-4">
              <h5 class="text-uppercase text-start">Useful links</h5>
              <hr class="mb-4 mt-0" />
      
              <ul class="list-unstyled text-start">
                <li class="mb-2">
                  <a href="#!" class="text-white">Your Account</a>
                </li>
                <li class="mb-2">
                  <a href="#!" class="text-white">Become an Affiliate</a>
                </li>
                <li class="mb-2">
                  <a href="#!" class="text-white">Shipping Rates</a>
                </li>
                <li>
                  <a href="#!" class="text-white">Help</a>
                </li>
              </ul>
            </div>
            <!--Grid column-->
      
            <!--Grid column-->
            <div class="col-md-3 mx-auto py-4">
              <h5 class="text-uppercase text-start">Contacts</h5>
              <hr class="mb-4 mt-0" />
      
              <ul class="list-unstyled text-start">
                <li class="mb-2">
                  <a href="#!" class="text-white"
                    ><i class="far fa-map mr-1"></i> New York, Avenue Street 10</a
                  >
                </li>
                <li class="mb-2">
                  <a href="#!" class="text-white"
                    ><i class="fas fa-phone-alt mr-1"></i> 042 876 836 908</a
                  >
                </li>
                <li class="mb-2">
                  <a href="#!" class="text-white"
                    ><i class="far fa-envelope mr-1"></i> company@example.com</a
                  >
                </li>
                <li>
                  <a href="#!" class="text-white"
                    ><i class="far fa-clock mr-1"></i> Monday - Friday: 10-17</a
                  >
                </li>
              </ul>
            </div>
            <!--Grid column-->
          </div>
          <!--Grid row-->
        </div>
        <!-- Grid container -->
      
        <!-- Copyright -->
        <div class="text-center p-3" style="background-color: rgba(0, 0, 0, 0.2)">
          © 2020 Copyright:
          <a class="text-white" href="https://mdbootstrap.com/">MDBootstrap.com</a>
        </div>
        <!-- Copyright -->
      </footer>
      
      
        
    
        
            
      import { Component } from '@angular/core';
      import { FormControl, FormGroup } from '@angular/forms';
      import { Observable } from 'rxjs';
      import { map, startWith } from 'rxjs/operators';
      
      export interface Item {
        id: number;
        category: string;
        name: string;
        rating: number;
        image: string;
        description: string;
        available: boolean;
        size: string[] | number[];
        condition: string;
        color: string;
        price: number;
        discount: number;
        gender: string;
        keywords?: string[];
      }
      
      export interface Filters {
        sale: string | null;
        sort: string | null;
        color: string | null;
        conditionNew: boolean | null;
        conditionUsed: boolean | null;
        conditionCollectible: boolean | null;
        conditionRenewed: boolean | null;
        rating: number | null;
        price: number | null;
        size34: number | null;
        size36: number | null;
        size38: number | null;
        size40: number | null;
      }
      
      @Component({
        selector: 'app-root',
        templateUrl: './app.component.html',
        styleUrls: ['./app.component.scss'],
      })
      export class AppComponent {
        filteredItems$: Observable<Item[]>;
        filtersGroup: FormGroup;
      
        defaultFilters: Filters = {
          color: null,
          sale: null,
          sort: null,
          conditionNew: null,
          conditionUsed: null,
          conditionCollectible: null,
          conditionRenewed: null,
          rating: null,
          price: null,
          size34: null,
          size36: null,
          size38: null,
          size40: null,
        };
      
        options = [
          { value: 'ratingdesc', label: 'Best rating' },
          { value: 'pricedesc', label: 'Higest price first' },
          { value: 'priceasc', label: 'Lowest price first' },
        ];
      
        noItemsFound = false;
      
        items: Item[] = [
          {
            id: 1,
            category: 'shirts',
            name: 'Fantasy T-shirt',
            rating: 4,
            image:
              'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/12.webp',
            description:
              'Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.',
            available: true,
            size: ['34', '36', '40'],
            condition: 'new',
            color: 'blue',
            price: 12.99,
            keywords: ['t-shirt', 'sweatshitrt'],
            discount: 0,
            gender: 'male',
          },
          {
            id: 2,
            category: 'shirts',
            name: 'Fantasy T-shirt',
            rating: 5,
            image:
              'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/13.webp',
            description:
              'Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.',
            available: true,
            size: ['34', '36', '40', '44'],
            condition: 'new',
            color: 'red',
            price: 12.99,
            discount: 0,
            gender: 'male',
          },
          {
            id: 3,
            category: 'shirts',
            name: 'Fantasy T-shirt',
            rating: 3,
            image:
              'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/14.webp',
            description:
              'Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.',
            available: true,
            size: ['34', '36'],
            condition: 'new',
            color: 'grey',
            price: 40.99,
            discount: 10,
            gender: 'male',
          },
          {
            id: 4,
            category: 'jackets',
            name: 'Denim Jacket',
            rating: 5,
            size: [],
            image:
              'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/15.webp',
            description:
              'Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.',
            available: true,
            condition: 'new',
            color: 'grey',
            price: 40.99,
            discount: 0,
            gender: 'unisex',
          },
          {
            id: 5,
            category: 'jeans',
            name: 'Ripped jeans',
            rating: 5,
            image:
              'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/11.webp',
            description:
              'Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.',
            available: true,
            size: ['34', '36', '38', '40'],
            condition: 'renewed',
            color: 'blue',
            price: 20.99,
            discount: 5,
            gender: 'female',
          },
          {
            id: 6,
            category: 'jeans',
            name: 'Boyfriend jeans',
            rating: 4,
            image:
              'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/10.webp',
            description:
              'Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.',
            available: false,
            size: ['34', '36', '38', '40'],
            condition: 'used',
            color: 'blue',
            price: 20.99,
            discount: 5,
            gender: 'female',
          },
          {
            id: 7,
            category: 'shirts',
            name: 'Ripped sweatshirt',
            rating: 4,
            image:
              'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/7.webp',
            description:
              'Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.',
            available: true,
            size: ['34', '36', '38', '40'],
            condition: 'collectible',
            color: 'white',
            price: 29.99,
            discount: 5,
            gender: 'female',
          },
          {
            id: 8,
            category: 'shirts',
            name: 'Longsleeve',
            rating: 4,
            image:
              'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/8.webp',
            description:
              'Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.',
            available: true,
            size: ['40'],
            condition: 'collectible',
            color: 'black',
            price: 120.99,
            discount: 0,
            gender: 'male',
          },
          {
            id: 8,
            category: 'shirts',
            name: 'Stripped sweatshirt',
            rating: 4,
            image:
              'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/6.webp',
            description:
              'Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.',
            available: true,
            size: ['40', '38', '36'],
            condition: 'new',
            color: 'white',
            price: 32.99,
            discount: 10,
            gender: 'female',
          },
          {
            id: 9,
            category: 'trousers',
            name: 'Red chinos',
            rating: 5,
            image:
              'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/5.webp',
            description:
              'Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.',
            available: true,
            size: ['40', '38', '36'],
            condition: 'new',
            color: 'red',
            price: 62.99,
            discount: 10,
            gender: 'female',
          },
          {
            id: 10,
            category: 'coats',
            name: 'Camel coat',
            rating: 5,
            image:
              'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/4.webp',
            description:
              'Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.',
            available: true,
            size: ['40', '38', '36'],
            condition: 'used',
            color: 'brown',
            price: 62.99,
            discount: 10,
            gender: 'female',
          },
          {
            id: 11,
            category: 'jeans',
            name: 'Blue jeans',
            rating: 5,
            image:
              'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/3.webp',
            description:
              'Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.',
            available: true,
            size: ['40', '38', '36'],
            condition: 'new',
            color: 'blue',
            price: 42.99,
            discount: 0,
            gender: 'female',
          },
          {
            id: 12,
            category: 'shirts',
            name: 'Orange T-shirt',
            rating: 3,
            image:
              'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/3.webp',
            description:
              'Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.',
            available: true,
            size: ['40', '38', '36'],
            condition: 'new',
            color: 'orange',
            price: 12.99,
            discount: 0,
            gender: 'female',
          },
          {
            id: 13,
            category: 'skirts',
            name: 'Ballerina skirt',
            rating: 4,
            image:
              'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/2.webp',
            description:
              'Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.',
            available: true,
            size: ['38', '36'],
            condition: 'collectible',
            color: 'white',
            price: 12.99,
            discount: 0,
            gender: 'female',
          },
        ];
      
        constructor() {
          this.filtersGroup = new FormGroup({
            color: new FormControl(),
            sale: new FormControl(),
            conditionNew: new FormControl(),
            conditionUsed: new FormControl(),
            conditionCollectible: new FormControl(),
            conditionRenewed: new FormControl(),
            rating: new FormControl(),
            price: new FormControl(), 
            size34: new FormControl(),
            size36: new FormControl(),
            size38: new FormControl(),
            size40: new FormControl(),
            sort: new FormControl()
          });
      
          this.filteredItems$ = this.filtersGroup.valueChanges.pipe(
            startWith(this.defaultFilters),
            map((controls: Filters) => {
              const { rating, price, color, sort } = controls;
              let items = this.items;
              const conditions = Object.keys(controls)
                .filter(
                  (control) =>
                    controls[control as keyof Filters] &&
                    control.startsWith('condition')
                )
                .map((string) => string.toLowerCase().replace('condition', ''));
      
              if (conditions.length > 0) {
                items = items.filter((item) =>
                conditions.some((condition) => item.condition === condition)
                );
              }
      
              if (rating) {
                items = items.filter((item) => item['rating'] === rating)
              }
              
              if (price) {
                if (price.toString().startsWith('<')) {
                  items = items.filter((item) => item['price'] < Number(price.toString().split('<')[1])); 
                }
                if (price.toString().startsWith('>')) {
                  items = items.filter((item) => item['price'] > Number(price.toString().split('>')[1])); 
                }
                if (price.toString().split('-').length === 2) {
                  items = items.filter((item) => item['price'] > Number(price.toString().split('-')[0]) && item['price'] < Number(price.toString().split('-')[1]))
                }
                
              }
      
              const sizes = Object.keys(controls)
              .filter(
                (control) =>
                  controls[control as keyof Filters] &&
                  control.startsWith('size')
              )
              .map((string) => Number(string.toLowerCase().replace('size', '')));
              this.noItemsFound = false;
              if (sizes.length > 0) {
                items = items.filter((item) =>
                  sizes.some((checkboxSize) => item['size'].some((itemSize) => itemSize === checkboxSize.toString()))
                );
              }
      
              if (color) {
                console.log(color)
                items = items.filter((item) => item['color'] === color); 
              }
      
              if (sort && sort.startsWith('price')) {
                items = items.sort((a, b) =>
                  sort.endsWith('asc') ? a['price'] - b['price'] : b['price'] - a['price']
                );
              }
      
              if (sort && sort.startsWith('rating')) {
                items = items.sort((a, b) =>
                  sort.endsWith('asc') ? a['rating'] - b['rating'] : b['rating'] - a['rating']
                );
              }
      
              if (items.length < 1) {
                this.noItemsFound = true;
              }
              return items;
            })
          );
        }
      
        clearFilters() {
          this.filtersGroup.reset();
        }
      }
      
        
    

Filters - API


Import

        
            
        import { ReactiveFormsModule } from '@angular/forms';
          …
          @NgModule ({
            ...
            imports: [ReactiveFormsModule],
            ...
          })